﻿#include<iostream>
using namespace std;
// 主要记录学习C++过程中的语法理解，与C部分代码不同，此处主要为日常笔记
 

// 1.C++入门基础
//C++向下兼容C语言，C的绝大多数语法C++是支持的
#include<stdio.h>
int main()
{
	printf("hello world!\n");
	return 0;
}
#include<iostream>//C++自己的输出
using namespace std;
int main()
{
	cout << "hello world!\n" << endl;
	return 0;
}
namespace lh1
{
	int a = 10;
	int b = 20;
}
int main()
{
	printf("%d", lh1::a);
	return 0;
}
//using namespace lh1;
//int main()
//{
//	printf("%d", a);
//	return 0;
//}
//既有变量，又有函数和自定义类型
namespace lh2
{
	int a = 10;
	int b = 20;
	double c = 11.1;
	char d = 'A';
	int Add(int a, int b)
	{
		return a + b;
	}
	class test//类
	{
		int e;
		float f;
	};
}
//嵌套定义
namespace lh3
{
	int a = 10;
	int b = 20;
	namespace lh4
	{
		char c = 'A';
		char d = 'B';
	}
}
//int a = 10;
//int main()
//{
//	int a = 20;
//	printf("%d", ::a);
//	return 0;
//}
#define _CRT_SECURE_NO_WARNINGS 1
int main()
{
	int a = 0;
	cout << "cin输入：" << endl;
	cin >> a;
	cout << "cout输出的是：" << a << endl;
	int b = 0;
	printf("sacnf输入的是：\n");
	scanf("%d", & b);
	printf("printf输出的是：%d\n", b);
	return 0;
}
//半缺省
int Add(int a, int b = 10, int c = 10)
{
	return a + b + c;
}
int main()
{
	cout << Add(20) << endl;
	cout << Add(20,20) << endl;
	cout << Add(20,20,20) << endl;
	return 0;
}
//全缺省
int Add(int a = 10, int b = 10, int c = 10)
{
	return a + b + c;
}
int main()
{
	cout << Add() << endl;
	cout << Add(20) << endl;
	cout << Add(20, 20) << endl;
	cout << Add(20, 20, 20) << endl;
	return 0;
}
//参数个数不同
int Add(int a, int b)//1
{
	return a + b;
}
int Add(int a, int b, int c)//2
{
	return a + b + c;
}
//函数参数类型不同
int Sub(int a, int b)//3
{
	return a - b;
}
double Sub(double a, double b)//4
{
	return a - b;
}
//函数参数顺序不同
double Add(double a, int b)//5
{
	return a + b;
}
double Add(int a, double b)//6
{
	return a + b;
}
int main()
{
	cout << Add(1, 2) << endl;//调用1，结果为3
	cout << Add(1, 2, 3) << endl;//调用2，结果为6
	cout << Sub(4, 3) << endl;//调用3，结果为1
	cout << Sub(4.1,3.2) << endl;//调用4，结果为0.9
	cout << Add(2.1, 1) << endl;//调用5，结果为3.1
	cout << Add(2, 3.1) << endl;//调用6，结果为5.1
	return 0;
}
//返回类型不同不能构成重载
int f(int a, int b)
{
	return a + b;
}
double f(int a, int b)
{
	return a + b;
}
int main()
{
	cout << f(1, 2) << endl;
	cout << f(3, 4) << endl;
	return 0;
}
void f()//1
{
	cout << "f()" << endl;
}
void f(int a = 10)//2
{
	cout << "f(int a)" << endl;
}
int main()
{
	//f();//由于缺省参数的存在，不传参时编译器不知道该调用哪个函数
	f(1);//给了参数做区分，所以调用2
	return 0;
}
int main()
{
	int a = 10;
	cout << a << endl;
	//int& b;//不初始化会报错
	int& b = a;
	b = 20;
	int& c = a;//一个变量可以有多个引用
	int& d = b;//也可以为引用变量取别名
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	int e = 30;
	b = e;//进行的操作是将e复制给b，而不是让b去引用e
	cout << b << endl;
	return 0;
}
//引用的应用
void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
	int a = 10, b = 20;
	Swap(a, b);
	cout << "a = " << a << "  " << "b = " << b << endl;
	return 0;
}
int main()
{
	const int a = 10;
	//int& b = a;//错误，a是const修饰，要用const引用
	const int& b = a;
	cout << b << endl;
	return 0;
}
int main()
{
	int a = 10;
	const int& b = a;
	b = 20;//const引用普通对象后其值不容修改
	return 0;
}
int main()
{
	int a = 2;
	int& b = a * 3;//表达式运算值存放在临时对象中，要用const引用
	double c = 5.02;
	int& d = c;//类型转化也是如此
	return 0;
}


// 2.类和对象的学习
//#include<iostream>
//using namespace std;
//int Add(int a = 10, int b = 10)
//{
//	return a + b;
//}
//int Add(int a , int b)
//{
//	return a + b;
//}
//int main()
//{
//	int ret = Add(1,2);
//	cout << ret << endl;
//	return  0;
//}
//#include<iostream>
//using namespace std;
//class student
//{
//public:
//	void Print()
//	{
//		cout << "Print(stu)" << endl;
//	}
//	class small 
//	{
//	public:
//		void Learn()
//		{	/*学习*/
//		}
//		void Eat()
//		{	/*吃饭*/
//		}
//		void Sleep()
//		{	/*睡觉*/
//		}
//		void Print();//只有声明
//	private:
//		char name;
//		int age;
//		int id;
//		char gender;
//	};
//
//};
//void student::small::Print()//定义要指定具体的类
//{
//	cout << "Print(small)" << endl;
//}
//int main()
//{
//	//把student看成大对象，small是嵌套在student中的小对象
//	student::small s;//创建小对象
//	student s1;//创建大对象
//	s.Print();
//	s1.Print();
//	return 0;
//}
//#include<iostream>
//using namespace std;
//class Data
//{
//public:
//	void Init(int year = 2024, int month = 10, int day = 6)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	void Print()
//	{
//		cout << _year << "/" << _month << "/" << _day << endl;
//	}
//private:
//	//为了区分成员变量,一般取名上习惯加_，也用以区分类中方法的参数，防止重名混乱，注意成员变量和类中方法的参数不是一个东西
//	int _year;//只是声明，没有开空间
//	int _month;
//	int _day;
//};
//class stu
//{
//private:
//	    char name;
//		int age;
//		int id;
//		char gender;
//};
//int main()
//{
//	Data d1;//实例化了对象，才开空间
//	Data d2;
//	d1.Init();
//	d1.Print();
//	d2.Init(2024, 4, 4);
//	d2.Print();
//	stu st;
//	int size1 = sizeof(d1);//size1为12
//	int size2 = sizeof(st);//size2为16
//	cout << size1 << endl;
//	cout << size2 << endl;
//	return 0;
//}
#include<iostream>
using namespace std;
class Data
{
public:
	//void Init(Data* const this, int year = 2024, int month = 10, int day = 6)---显示不允许
	//void Init(/*Data* const this, */int year = 2024, int month = 10, int day = 6)//隐式给出
	//{
	//	this->_year = year;//允许
	//	this->_month = month;
	//	this->_day = day;
	//}
	void Print()
	{
		cout << this << endl;
		//cout << _year << endl;
		//cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	//为了区分成员变量,一般取名上习惯加_，也用以区分类中方法的参数，防止重名混乱，注意成员变量和类中方法的参数不是一个东西
	int _year;//只是声明，没有开空间
	int _month;
	int _day;
};
class stu
{
private:
	char name;
	int age;
	int id;
	char gender;
};
int main()
{
	Data d1;//实例化了对象，才开空间
	Data d2;
	Data* d3 = nullptr;
	//d1.Init();
	//d1.Print();
	//d2.Init(2024, 4, 4);
	//d2.Print();
	//d3->Init();
	d3->Print();
	stu st;
	int size1 = sizeof(d1);//size1为12
	int size2 = sizeof(st);//size2为16
	cout << size1 << endl;
	cout << size2 << endl;
	return 0;
}
//#include<iostream>
//using namespace std;
//class Data
//{
//public:
//	Data()//默认构造函数
//	{
//		_year = 2024;
//		_month = 10;
//		_day = 13;
//	}
//	Data(int year, int month, int day)//是默认构造函数的重载，但需要传参，所以属于构造函数的范畴
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	/*Data(int year = 2024,int month = 10,int day = 13)//默认构造函数
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}*/
//	void Print()
//	{
//		cout << _year << "/" << _month << "/" << _day << endl;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//int main()
//{
//	Data d1;//调用默认构造函数
//	d1.Print();
//	Data d2(2024,4,4);//调用传参构造函数
//	d2.Print();
//	return 0;
//}
//#include<iostream>
//using namespace std;
//class Stack
//{
//public:
//	Stack(int capacity = 4)
//	{
//		_a = (int*)malloc(sizeof(int) * capacity);
//		if (nullptr == _a)
//		{
//			perror("malloc申请空间失败");
//			return;
//		}
//		_capacity = capacity;
//		_top = 0;
//		cout << "调用了Stack(int capacity = 4)" << endl;
//	}
//	~Stack()
//	{
//		free(_a);
//		_a = nullptr;
//		_top = _capacity = 0;
//		cout << "调用了~Stack()" << endl;
//	}
//private:
//	int* _a;
//	int _top;
//	int _capacity;
//};
//class MyQueue
//{
//public:
//	MyQueue()
//	{
//		cout << "调用了MyQueue()" << endl;
//	}
//	~MyQueue()
//	{
//		cout << "调用了~MyQueue()" << endl;
//	}
//private:
//	Stack pushst;
//	Stack popst;
//};
//int main()
//{
//	Stack st;
//	MyQueue q;
//	return 0;
//}
#include<iostream>
using namespace std;
class Data
{
public:
	Data()
	{
		_year = 2024;
		_month = 10;
		_day = 13;
	}
	Data(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data d1;//先创建d1
	d1.Print();
	Data d2(d1);//再调用拷贝构造，用d1去初始化d2，乃至初始化后面的d3，d4
	Data d3 = d1;
	Data d4;
	d4 = d1;
	d2.Print();
	d3.Print();
	d4.Print();
	return 0;
}
//#include<iostream>
//using namespace std;
//class Data
//{
// friend ostream& operator<<(ostream& out, const Data& d);//声明放在类中，用friend连接，且为支持运算符的连续性，返回值应为ostream&
// friend istream& operator>>(istream& in, Data& d);
//public:
//	Data(int year=2024,int month=10,int day=14)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	Data(const Data& d)//拷贝构造
//	{
//		_year = d._year;
//		_month = d._month;
//		_day = d._day;
//	}
//	void Print()
//	{
//		cout << _year << '/' << _month << '/' << _day << endl;
//	}
//	bool operator==(const Data& d)//对==的重载
//	{
//		return _year == d._year &&
//			_month == d._month &&
//			_day == d._day;
//	}
//	Data& operator++()//对前置++的重载
//	{
//		cout << "前置++" << endl;
//		++_day;//这里只是简单对_day前置++，后面会有更具体的日期类的运算符重载函数实现
//		return *this;
//	}
//	Data operator++(int)//对后置++的重载
//	{
//		cout << "后置++" << endl;
//		Data tmp = _day++;//同理，只是简单实现
//		return tmp;
//	}
//	
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//ostream& operator<<(ostream& out, const Data& d)//用friend连接来就不要用::指定类域了
//{
//	out << d._year << "年/" << d._month << "月/" << d._day << "日" << endl;
//	return out;
//}
//istream& operator>>(istream& in, Data& d)
//{
//	cout << "请依次输入合法的年/月/日" << endl;
//	cin >> d._year >> d._month >> d._day;
//	return cin;
//}
//int main()
//{
//	Data d1;
//	Data d2(2024, 4, 4);
//	Data d3(2023, 4, 4);
//	Data d4;
//	cout << (d1.operator==(d2)) << endl;//1.为==的显示调用
//	cout << (d1 == d2) << endl;//2.为==的隐式调用，编译器会转化成 d1.operator==(d2),由于d1与d2不同所以输出0
//	++d2;                      //隐式调用前置++，其显示为d2.operator++()
//	cout << "前置++的结果为：" << d2 << endl;//3.展示前置++
//	d3++;                      //隐示调用后置++，其显示为d3.operator++(0);
//	cout << "后置++的结果为：" << d3 << endl;//4.展示后置++
//	cin >> d4;                 //5.为 >> 的隐示调用，其显示为d4.operator >> (cin,d4)
//	cout << d1 << d2 << d3 << d4 << endl;//6.为 << 的隐式调用,其实3和4也有 << 隐式调用的体现
//	return 0;
//}
//#include<iostream>
//using namespace std;
//class Data
//{
//	friend ostream& operator<<(ostream& out, const Data& d);
//public:
//	Data(int year = 2024, int month = 10, int day = 14)//默认构造函数
//	{
//		cout << "普通构造" <<endl;
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	Data(Data& d)//拷贝构造函数
//	{
//		cout << "拷贝构造" << endl;
//		_year = d._year;
//		_month = d._month;
//		_day = d._day;
//	}
//	//d1=d2
//	//Data& operator=(Data* const this,const Data& d)---this是左操作数d1，d是右操作数d2,将d2赋值给d1
//	Data& operator=(const Data& d)//赋值运算符重载函数
//	{
//		//this是指向左操作数(d1)，d是指向右操作数(d2)
//		cout << "赋值运算符重载" << endl;
//		this->_year = d._year;
//		this->_month = d._month;
//		this->_day = d._day;
//		return *this;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//ostream& operator<<(ostream& out, const Data& d)
//{
//	out << d._year << "年/" << d._month << "月/" << d._day << "日" << endl;
//	return out;
//}
//int main()
//{
//	Data d1;
//	cout << d1 << endl;
//	Data d2(2024, 4, 4);
//	cout << d2 << endl;
//	Data d3(d1);     //拷贝构造，等价于Data d3 = d1;其中d3还未被创建
//	cout << d3 << d1 << endl;
//	d1 = d2;         //赋值运算符重载，其中d1与d2都是已经被创建了的
//	cout << d1 << d2 << endl;
//	return 0;
//}
//#include<iostream>
//using namespace std;
//class student
//{
//public:
//	student()
//	{
//		year = 18;
//	}
//	//void Print() const 等价于 void Print(const student* const this)
//	void Print() const
//	{
//		//this->year = 20;//error 由于正在通过常量对象访问“year”，因此无法对其进行修改
//		cout << year << endl;
//	}
//private:
//	int year;
//};
//int main()
//{
//	student hl;
//	hl.Print();
//	return 0;
//}
#include<iostream>
using namespace std;
class Data
{
public:
	Data* operator&()//普通取地址重载函数,返回值是指针
	{
		return this;//返回的是Data*类型
	}
	const Data* operator&() const
	{
		return this;//const取地址重载函数，返回的是const Data*类型
		//return nullptr;//也可返回任意地址
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data d1;
	cout << &d1 << endl;
	return 0;
}
#include<iostream>
using namespace std;
//class Time
//{
//	 friend ostream& operator<<(ostream& out, const Time& t);
//public:
//	Time(int hour)//非默认构造的构造函数
//		:_hour(hour)
//	{
//		cout << "Time(int hour)" << endl;
//	}
//private:
//	int _hour;
//};
//class Date
//{
//public:
//	Date(int& ra, int year = 2024, int month = 10, int day = 18)
//		: _year(year)   //初始化列表进行初始化工作
//		, _month(month)
//		, _day(day)
//		, _t(13)     //_t,ra,n必须在初始化列表中进行初始化
//		, ra(ra)
//		, n(4)
//	{
//		cout << _year << "/" << _month << "/" << _day << "/" << _t << "/" << ra << "/" << n << endl;
//		_year = 2022;  //函数体内部是赋值操作
//		_month = 4;
//		_day = 4;
//		_t = 5;       //编译器隐式把int转化为Time类型去构造
//		ra = 5;
//		cout << _year << "/" << _month << "/" << _day << "/" << _t << "/" << ra << "/" << n << endl;//重载了<<
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//	Time _t;
//	int& ra;
//	const int n;
//};
//ostream& operator<<(ostream& out, const Time& t)
//{
//	out << t._hour;
//	return out;
//}
//int main()
//{
//	int a = 0;
//	Date d1(a);
//	return 0;
//}
//class A
//{
//public:
//	A(int h)      //构造1
//		:_h(h)
//	{
//		cout << "A(int h)" << endl;
//		cout << _h << " " << _l << endl << endl;
//	}
//	A(int h,int l)//构造2
//		:_h(h)
//		,_l(l)
//	{
//		cout << "A(int h,int l)" << endl;
//		cout << _h << " " << _l << endl << endl;
//	}
//	int Get() const
//	{
//		return _h + _l;
//	}
//private:
//	int _h = 1;
//	int _l = 2;
//};
//struct B
//{
//	explicit B(const A& a)      //用A类型对象去拷贝构造B类型对象
//		:_hl(a.Get()) 
//	{
//		cout << "B(const A& a) " << endl;
//		cout << _hl << endl << endl;
//	};
//	int _hl;
//};
//int main()
//{
//	A a1 = 66;       //单参数构造，对应构造1
//	A a2 = { 66,72 };//多参数构造，对应构造2
//	B b1 = a1;       //自定义类型去初始化自定义类型 
//	B b2 = a2;
//	return 0;
//}
////写一个类，用来计算程序中产生的对象个数
//class A
//{
//public:
//	A() 
//	{	++_count; }
//	A(const A& a)
//	{	++_count; }
//	static int get_count()
//	{	return _count; }
//	~A()
//	{	--_count; }
//private:
//	static int _count;//类内声明
//};
//int A::_count = 0;    //类外定义
//int main()
//{
//	cout << A::get_count() << endl;
//	A a1, a2;
//	cout << A::get_count() << endl;
//	cout << a1.get_count() << endl;
//	A a3(a1);
//	cout << A::get_count() << endl;
//}
//class B;//前置声明
//class A
//{
//	friend void func(const A& a, const B& b);//A类中进行友元函数声明,表示func是A的友元---A声明有个朋友是func
//private:
//	int _a1 = 66;
//	int _a2 = 72;
//};
//class B
//{
//	friend void func(const A& a, const B& b);//B类中进行友元函数声明
//private:
//	int _b1 = 72;
//	int _b2 = 66;
//};
//void func(const A& a, const B& b)//定义不用加friend
//{
//	cout << a._a1 << endl;
//	cout << b._b2 << endl;
//}
//class C
//{
//	friend class D;//得加class，C类中进行友元类声明，表示D是C的友元---C家族声明与D家族交好
//private:
//	int _c1 = 2024;
//	int _c2 = 4;
//};
//class D
//{
//public:
//	void Print1(const C& c)
//	{	cout << c._c1 << "/" << _d2 << endl; }
//	void Print2(const C& c)
//	{	cout << _d1 << "/" << c._c2 << endl; }
//private:
//	int _d1 = 2024;
//	int _d2 = 8;
//};
//int main()
//{
//	C c1;
//	D d1;
//	d1.Print1(c1);//输出2024/8
//	d1.Print2(c1);//输出2024/4
//	return 0;
//}
//class A
//{
//private:
//	int _a1 = 2024;
//	int _a2 = 4;
//public:
//	class B
//	{
//	public:
//		void Print(const A& a)
//		{
//			cout << a._a1 << "/" << a._a2 << "/" << _b << endl;
//		}
//	private:
//		int _b = 4;
//	};
//};
//int main()
//{
//	A a;
//	A::B b;                   //需指定类域进行实例化
//	cout << sizeof(b) << endl;//b对象是4个字节空间
//	cout << sizeof(a) << endl;//a对象是8个字节空间，说明a对象不包含b对象，b对象是独立的对象
//	b.Print(a);               //输出2024/4/4
//	return 0;
//}
//class A
//{
//private:
//	static int a;
//};
//int main()
//{
//	A a;
//	cout << sizeof(a) << endl;
//	return 0;
//}
class A
{
public:
	A(int a = 6)
		:_a(a)
	{
		cout << "A(int a = 6)" << endl;
		cout << _a << endl << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
class Get_N
{
public:
	int Get()
	{
		return n;
	}
private:
	int n = 100;
};
int main()
{
	A a;                          //有名对象
	A(66);                        //匿名对象
	cout << Get_N().Get() << endl;//匿名对象的使用场景
	return 0;
}


// 3.内存管理与模板初阶
//int n1 = 1;
//static int n2 = 2;
//void Test()
//{
//	static int n3 = 3;
//	int n4 = 4;
//	int n5[10] =    { 5,5,5,5,5, };
//	char n6[] =      "666666";
//	const char* n7 = "7777777";
//	int* n8 =       (int*)malloc(sizeof(int) * 4);
//	int* n9 =       (int*)calloc(4, sizeof(int));
//	int* n10 =      (int*)realloc(n9, sizeof(int) * 4);
//	free(n8);
//	free(n10);
//}
//int main()
//{
//	int* p1 = (int*)malloc(sizeof(int) * 4);
//	int* p2 = (int*)calloc(4, sizeof(int));
//	int* p3 = (int*)realloc(p2, 8 * sizeof(int));
//	free(p1);
//	free(p2);
//	free(p3);
//	return 0;
//}
//void Test()
//{
//	//动态申请1个int类型空间
//	int* p1 = new int;
//	//动态申请1个int类型空间并初始化为2004，()中写初始化值
//	int* p2 = new int(2004);
//	//动态申请10个int类型空间，[]中写申请类型个数
//	int* p3 = new int[10];
//  //error: 无法使用带圆括号的初始值设定项初始化数组
//	//int* p4 = new int[10](2024);
//	delete p1;//申请是new，释放是delete
//	delete p2;
//	delete[] p3;//申请是new[],释放是delete[]
//}
//class A
//{
//public:
//	A(int a1 = 0,int a2 = 0)
//		:_a1(a1)
//		,_a2(a2)
//	{	
//		cout << _a1 << " " << _a2 << endl;
//		cout << "A(int a1 = 0,int a2 = 0)" << endl; 
//	}
//	~A()
//	{	cout << "~A()" << endl << endl; }
//private:
//	int _a1;
//	int _a2;
//};
//
//int main()
//{
//	A* p = new A[3];
//	delete p;
//	return 0;
//}
//int main()
//{
//	A* p1 = new A;
//	delete p1;
//	A* p2 = new A(2024, 4);
//	delete p2;
//	//error: 无法使用带圆括号的初始值设定项初始化数组
//	//A* p3 = new A[3](2005, 8);
//	A* p3 = new A[3];
//	delete[] p3;
//	return 0;
//}
//无模板前，使用交换函数要根据不同的数据类型去写不同的函数，导致代码量的增多
//void Swap(int& a, int& b)
//{
//	int tmp = a;
//	a = b;
//	b = tmp;
//}
//void Swap(double& a, double& b)
//{
//	double tmp = a;
//	a = b;
//	b = tmp;
//}
//int main()
//{
//	int a = 2004, b = 2005;
//	Swap(a, b);
//	cout << a << " " << b << endl;
//	double c = 2004.4, d = 2005.5;
//	Swap(c, d);
//	cout << c << " " << d << endl;
//}
//有模板后，对于交换函数只要写出一个模板函数即可，初步体现了泛型编程
//template<class T>
//void Swap(T& a, T& b)
//{
//	T tmp = a;
//	a = b;
//	b = tmp;
//}
//int main()
//{
//	int a = 2004, b = 2005;
//	Swap(a, b);
//	cout << a << " " << b << endl;
//	double c = 2004.4, d = 2005.5;
//	Swap(c, d);
//	cout << c << " " << d << endl;
//	return 0;
//}

//template<class T>
//T Add(const T& a, const T& b)//涉及类型转换时产生临时对象
//{
//	return a + b;
//}
//int main()
//{
//	int a1 = 10, a2 = 20;
//	double b1 = 10.1, b2 = 20.2;
//	cout << Add(a1, a2) << endl;//隐式实例化
//	cout << Add(b1, b2) << endl;
//	//error: “Add”: 未找到匹配的重载函数，要想解决：1.用户自己强转，2.使用显示实例化
//	//cout << Add(a1, b1) << endl;
//	cout << Add(a1, (int)b1) << endl;
//	cout << Add<int>(a1, b1) << endl;//显示类型转换
//	cout << Add<double>(a2, b2) << endl;
//	return 0;
//}
////1.普通加法函数
//int Add(int& a, int& b)
//{
//	return a + b;
//}
////2.通用的模板加法函数
//template<class T1,class T2>
//T1 Add(const T1& a, const T2& b)
//{
//	return a + b;
//}
//int main()
//{
//	int a1 = 10, a2 = 20;
//	double b1 = 2004.4, b2 = 2005.8;
//	cout << Add(a1, a2) << endl;//与1最匹配，会去调用1
//	cout << Add(a1, b1) << endl;//与2最匹配，会去调用2
//	cout << Add<double>(a2, b2) << endl;//显示调用模板函数，则会调用2
//	return 0;
//}
template<class T>
class Stack
{
public:
	Stack(int size = 0, int capacity = 4, T* arr = nullptr)
		: _size(size)
		, _capacity(capacity)
		, _arr(arr)
	{
		_arr = new T[_capacity];
	}
	void Push(const T& data);
	void Print()
	{
		cout << _arr[0] << " " << _arr[1] << " " << _arr[2] << " " << _arr[3] << endl;
	}
	~Stack()
	{
		delete[] _arr;
		_arr = nullptr;
		_size = _capacity = 0;
	}
private:
	T* _arr;
	int _size;
	int _capacity;
};
template<class T>
void Stack<T>::Push(const T& data)
{
	_arr[_size++] = data;
}
int main()
{
	Stack<int> s1;
	Stack<double> s2;
	//Stack只是模板，Stack<int>和Stack<double>才是类型
	s1.Push(1); s1.Print();
	s2.Push(1.1); s2.Print();
	return 0;
}
#include<iostream>
#include<map>
using namespace std;
//int main()
//{
//	int n = 100;
//	auto p1 = &n;//p1与p2没有区别
//	auto* p2 = &n;
//	auto& r1 = n;//引用类型必须加 &
//	cout << *p1 << " " << *p2 << " " << r1 << endl;//输出100  100  100
//	auto n1 = 1, n2 = 1.01, n3 = 'a';
//	return 0;
//}
//int func1(auto a, auto b)
//{
//	return a + b;
//}
//auto func2()
//{
//	return 6;
//}
//int main()
//{
//	auto n = func2();
//	cout << n << endl;
//	return 0;
//}
//int main()
//{
//	//不能直接用来声明数组
//	auto[10] = { 1,2,3,4 };
//	return 0;
//}
//int main()
//{
//	std::map<std::string, std::string> dict = { { "apple", "苹果" },{ "orange",
//   "橙子" }, {"pear","梨"} };
//	// auto的用武之地
//	//std::map<std::string, std::string>::iterator it = dict.begin();
//	auto it = dict.begin();
//	return 0;
//}
//int main()
//{
//	int arr[] = { 1,2,3,4,5 };
//	//普通遍历方式：
//	cout << "普通遍历方式：";
//	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
//	{
//		cout << arr[i] << " ";
//	}
//	cout << endl;
//	//C++11的范围for：
//	cout << "C++11的范围for：";
//	for (auto n : arr)
//	{
//		cout << n << " ";
//	}
//	cout << endl;
//	return 0;
//}
//namespace hl //放入namespace hl 中模拟实现,防止与库里的string重名
//{
//	class string
//	{
//	public:
//		//成员函数...
//	private:
//        char buff[16];           //vs编译器下会先开一个buff数组用来解决短小字符串情景(注意实际可用15个字节，最后一个要放'\0')
//		char* _arr = nullptr;    //底层是字符数组,当字符串长度大于15时才会在堆上申请空间
//		size_t _size = 0;        //当前有效字符个数
//		size_t _capacity = 15;   //当前字符串的容量大小，vs下有buff数组，所以刚开始是15
//		static const size_t npos;//表示整型的最大值
//	};
//	size_t const string::npos = -1;
//}
//#include<iostream>
//#include<string>
//using namespace std;
//int main()
//{
//	string s1;                //空构造s1
//	string s2("hello world!");//用C的字符串去构造s2对象
//	string s3(s2);            //用s2对象去拷贝构造s3对象
//	cout << " s1对象为：" << s1 << endl;
//	cout << " s2对象为：" << s2 << endl;
//	cout << " s3对象为：" << s3 << endl;
//	return 0;
//}


// 4.string类的学习
#include<iostream>
#include<string>
//测试size/length/capacity/empty
void TestString1()
{
	string s1;//空字符串
	cout << s1.size() << endl;  //输出0
	cout << s1.length() << endl;//length与size一致，输出0
	cout << s1.capacity() << endl;//输出15
	cout << s1.empty() << endl;  //输出1
	cout << endl;

	string s2("hello world");//非空字符串
	cout << s2.size() << endl;//输出11
	cout << s2.length() << endl;//输出11
	cout << s2.capacity() << endl;//输出15
	cout << s2.empty() << endl;//输出0
}
//测试clear
void TestString2()
{
	string s1("我是一个苦逼的计算机学生，没有对象，没有甜甜的爱情，只有一行行的代码");
	cout << "清空前：";
	//输出68 79 0
	cout << s1.size() << " " << s1.capacity() << " " << s1.empty() << endl;
	s1.clear();
	cout << "清空后：";
	//输出0 79 1---说明clear并不会改变底层的容量大小
	cout << s1.size() << " " << s1.capacity() << " " << s1.empty() << endl;
}
//测试reserve
void TestString3()
{
	string s2("我是一个苦逼的计算机学生，没有对象，没有甜甜的爱情，只有一行行的代码");
	string s3;
	//在已经知道字符串大小的时候可以提前开好空间，避免频繁扩容影响效率
	s3.reserve(100);
	//输出： 111(底层还有个buff数组)
	cout << s3.capacity() << endl;
	s3 = s2;
	//输出：68 79 0
	cout << s2.size() << " " << s2.capacity() << " " << s2.empty() << endl;
	//输出：68 111 0
	cout << s3.size() << " " << s3.capacity() << " " << s3.empty() << endl << endl;

	//当要预留的空间小于当前容量时，字符串的有效个数，字符串当前的容量都不会改变 
	s3.reserve(0);
	cout << s3.size() << " " << s3.capacity() << endl;//输出68 111
	s3.reserve(85);
	cout << s3.size() << " " << s3.capacity() << endl;//输出68 111
}
//测试resize
void TestSting4()
{
	string s1("我是一个苦逼的计算机学生，没有对象，没有甜甜的爱情，只有一行行的代码");
	cout << s1.size() << " " << s1.capacity() << endl;//输出68 79

	//使有效字符个数减少，底层的容量不变
	s1.resize(24);
	cout << s1 << endl;
	cout << s1.size() << " " << s1.capacity() << endl;//输出24 79

	//当不超过当前容量时，增大有效字符个数，并用字符a填充多出的空间
	s1.resize(75, 'a');
	cout << s1 << endl;
	cout << s1.size() << " " << s1.capacity() << endl;//输出75 79

	//当超过当前容量时，先扩容，再增大有效字符个数，并用字符b填充多出的空间
	s1.resize(90, 'b');
	cout << s1 << endl;
	cout << s1.size() << " " << s1.capacity() << endl;//输出90 118
}
//int main()
//{
//	//TestString1();
//	//TestString2();
//	//TestString3();
//	TestSting4();
//	return 0;
//}
//int main()
//{
//	string s1("abcdefghi");
//	//正向迭代器变量
//	string::iterator itb = s1.begin();
//	string::iterator ite = s1.end();
//	cout << *itb << endl;//输出a
//	cout << *(ite - 1) << endl;//防止越界，输出i
//	//反向迭代器变量
//	string::reverse_iterator ritb = s1.rbegin();
//	string::reverse_iterator rite = s1.rend();
//	cout << *ritb << endl;//输出i
//	cout << *(rite - 1) << endl;//防止越界，输出a
//	return 0;
//}
//string容器的遍历方式
//void TestSting5()
//{
//	string s("abcdefghi");
//	//普通遍历方式：
//	cout << "普通遍历方式：";
//	for (int i = 0; i<s.size();i++)
//	{
//		cout << s[i] << " ";
//	}
//	cout << endl;
//	//C++11的范围for：
//	cout << "C++11的范围for：";
//	for (auto _s : s)
//	{
//		cout << _s << " ";
//	}
//	cout << endl;
//	//范围for的底层实质是迭代器
//	//正向迭代器遍历--正向打印
//	cout << "正向迭代器遍历：";
//	auto itb = s.begin();
//	while (itb != s.end())
//	{
//		cout << *(itb) << " ";
//		++itb;
//	}
//	cout << endl;
//	//反向迭代器遍历--反向打印
//	cout << "反向迭代器遍历：";
//	auto ritb = s.rbegin();
//	while (ritb != s.rend())
//	{
//		cout << *(ritb) << " ";
//		++ritb;
//	}
//}
//int main()
//{
//	TestSting5();
//	return 0;
//}
//测试push_back/append/+=
//void TestSting6()
//{
//	string s1("hms");
//	cout << s1 << endl;
//	//append
//	s1.append(" is very beautiful");
//	cout << s1 << endl;
//	//push_back
//	s1.push_back('!');
//	cout << s1 << endl;
//	string s2("lm");
//	cout << s2 << endl;
//	//+=
//	s2 += " is very handsome!";
//	cout << s2 << endl;
//}
//测试c_str/find/substr
//void TestSting7()
//{
//	//c_str
//	string s1("shuai_ming");
//	cout << s1.c_str() << endl;
//	//find
//	size_t find = s1.find('_', 0);
//	cout << s1[find] << endl;
//	//substr
//	cout << s1.substr(find) << endl;//默认有个缺省值npos
//	cout << s1.substr(find, 5) << endl;
//}
//getline
//void TestString8()
//{
//	string s1;//空串
//	cout << "s1的getline()之前：";
//	cout << s1 << endl ;
//	cout << "请输入s1的getline()的内容：";
//	getline(cin, s1);
//	cout << "s1的getline()之后：";
//	cout << s1 << endl;
//	string s2("hello world!");//非空串
//	cout << "s2的getline()之前：";
//	cout << s2 << endl;
//	cout << "请输入s2的getline()的内容：";
//	getline(cin, s2);
//	cout << "s2的getline()之后：";
//	cout << s2 << endl;
//}
//void Teststring9()
//{
//	string s1("扣1送地狱火");
//	cout << "cin前的s1：" << s1 << endl;
//	cin >> s1;
//	cout << "cin后的s1：";
//	cout << s1 << endl;
//	/*string s2;
//	getline(cin, s2);
//	cout << s2 << endl;*/
//}
int main()
{
	//TestSting6();
	//TestString8();
	//Teststring9();
	return 0;
}


// 5.vector的学习
#include<iostream>
#include<string>
#include <vector>
#include<algorithm>
using namespace std;
void test_constructor()
{
	//无参构造
	vector<int> v1;
	for (auto e : v1)
		cout << e << " ";
	cout << endl;
	//构造并初始化n个val
	vector<int> v2(10, 1);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	//也可以嵌套其他容器去初始化
	string s1("hello world");
	vector<string> vv1(10, s1);
	for (auto e : vv1)
		cout << e << " ";
	cout << endl;
	//拷贝构造
	vector<int> v3(v2);
	for (auto e : v3)
		cout << e << " ";
	cout << endl;
	//使用迭代器进行初始化构造
	//vector<int>::iterator first = v3.begin() + 5;
	auto first = v3.begin() + 5;
	//vector<int>::iterator last = v3.end() - 1;
	auto last = v3.end() - 1;
	vector<int> v4(first, last);
	for (auto e : v4)
		cout << e << " ";
	cout << endl;
	//赋值运算符重载函数
	vector<int> v5;
	v5 = v3;
	for (auto e : v5)
		cout << e << " ";
	cout << endl;
}
void test_iterator()
{
	string s1(" hello world!");
	vector<string> v1(3, s1);//用三个s1构造v1
	//for (auto e : v1)
	//	cout << e << " ";
	//cout << endl;
	vector<string>::iterator first = v1.begin();
	auto last = v1.end() - 1;
	vector<string> v2(first, last);
	//for (auto e : v2)
	//	cout << e << " ";
	//cout << endl;
	// vector<int> vv(2, 1);
	//auto it = vv.cbegin();
	//*it += 2;
	//三种遍历方式
	vector<string> v3(1, s1);
	for (int i = 0; i < v3.size(); i++)//普通
		cout << v3[i];
	cout << endl;
	auto begin = v3.cbegin();
	auto end = v3.cend();
	//cout<<*begin;
	while (begin != end)//迭代器
	{
		cout << *begin;
		++begin;
	}
	cout << endl;
	for (auto e : v3)//范围for
		cout << e;
	cout << endl;
	vector<int> v4;
	v4.reserve(5);
	v4.push_back(1);
	v4.push_back(2);
	v4.push_back(3);
	v4.push_back(4);
	v4.push_back(5);
	auto crbegin = v4.crbegin();
	auto crend = v4.crend();
	while (crbegin != crend)
	{
		cout << *crbegin << " ";
		++crbegin;
	}
	cout << endl;
	auto cbegin = v4.cbegin();
	auto cend = v4.cend();
	//cout<<*begin;
	while (cbegin != cend)//迭代器
	{
		cout << *cbegin << " ";
		++cbegin;
	}
	cout << endl;
}
void test_capacity()
{
	vector<int> v1;
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	vector<int> v2(10, 5);
	cout << v2.size() << " " << v2.capacity() << " " << v2.empty() << endl;
	v1.reserve(6);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.resize(6);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.reserve(0);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.resize(0);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
}
void test_modify()
{
	vector<int> v1;
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(1);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(2);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(3);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(4);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(5);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.push_back(6);
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	v1.pop_back();
	cout << v1.size() << " " << v1.capacity() << " " << v1.empty() << endl;
	auto find = std::find(v1.begin(), v1.end(), 4);
	cout << *find << endl;
	vector<int> v2(5, 6);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.insert(v2.begin(), 111);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.insert(v2.begin() + 3, 111);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.insert(v2.end(), 111);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.insert(v2.begin(), 6, 999);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.insert(v2.begin(), find, v1.end());
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	v2.erase(v2.begin() + 1);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	auto find1 = std::find(v2.begin(), v2.end(), 999);
	auto find2 = std::find(v2.begin(), v2.end(), 111);
	v2.erase(find1, find2);
	for (auto e : v2)
		cout << e << " ";
	cout << endl;
	//交换
	vector<string> v3;
	v3.push_back("hello world!");
	for (auto e : v3)
		cout << e << " ";
	cout << endl;
	vector<string> v4;
	v4.push_back("world hello!");
	for (auto e : v4)
		cout << e << " ";
	cout << endl;
	v4.swap(v3);
	for (auto e : v3)
		cout << e << " ";
	cout << endl;
	for (auto e : v4)
		cout << e << " ";
	cout << endl;
}
int main()
{
	//test_constructor();
	//test_iterator();
	//test_capacity();
	test_modify();
	return 0;
}


// 6.继承的学习
#include<iostream>
#include<vector>
using namespace std;
////非继承
//class Student
//{
//public:
//	// 身份认证
//	void identity()
//	{ /* ... */ }
//	// 学习 
//	void study()
//	{ /* ... */ }
//protected:
//	string _name; // 姓名 
//	string _address; // 地址 
//	string _tel; // 电话 
//	int _age; // 年龄 
//	string _stuid; // 学号 
//};
//class Teacher
//{
//public:
//	// 身份认证
//	void identity()
//	{ /* ... */ }
//	// 教书 
//	void teach()
//	{ /* ... */ }
//protected:
//	string _name; // 姓名 
//	string _address; // 地址 
//	string _tel; // 电话 
//	int _age; // 年龄 
//	string _title; // 职称
//};
//继承
//class Person//基类
//{
//public:
//	// 身份认证
//	void identity()
//	{ cout << "void identity()" << endl; }
//protected:
//	string _name; 
//	string _address; 
//	string _tel; 
//	int _age; 
//};
//class Student :public Person
//{
//public:
//	void study() { cout << "void study()" << endl; }
//protected:
//	string _stuid;
//};
//class Teacher :public Person
//{
//public:
//	void teach() { cout << "void teach()" << endl; }
//protected:
//	string _title;
//};
//class Person
//{
//public:
//	void Print1()  { cout << "void Print2()" << endl; }
//protected:
//	void Print2()  { cout << "void Print2()" << endl; }
//private:
//	string _name = "小明";
//};
//class Student :public Person// 公有继承---基类的public与protected在派生类中限定不变
//{
//protected:
//	string _stuid;
//};
//class Student :protected Person// 保护继承---基类的public与proteceted在派生类中限定都变为protected
//{
//protected:
//	string _stuid;
//};
//class Student :private Person// 私有继承---基类的public与proteceted在派生类中限定都变为private
//{
//protected:
//	string _stuid;
//};
//让Stack继承vector，去实现Stack的功能
//namespace hl
//{
//	template<class T>
//	class Stack :public std::vector<T>
//	{
//	public:
//		void push(const T& x)            //必须指定类域，因为是按需实例化，
//		{	push_back(x); }              //此时还没有实例化vector中的push_back                                                           
//		const T& top()                   //编译器会找不到对应的函数接口而报错
//		{   return vector<int>::back(); }//同理
//		void pop()
//		{	vector<int>::pop_back(); }
//		bool empty()
//		{	return vector<int>::empty(); }
//	};
//}
//int main()
//{
//	//Student s;
//	//Teacher t;
//	//s.identity(); t.identity();
//	//s.study(); t.teach();
//	hl::Stack<int> st;
//	st.push(1);
//	st.push(2);
//	st.push(3);
//	while (!st.empty())
//	{
//		cout << st.top() << endl;
//		st.pop();
//	}
//	return 0;
//}
//class Person
//{
//protected:
//	string _name; 
//	string _sex;  
//	int _age; 
//};
//class Student : public Person
//{
//public:
//	int _stuid; 
//};
//int main()
//{
//	Student sobj;
//	// 1.派生类对象可以赋值给基类的指针/引用 
//	Person* pp = &sobj;
//	Person& rp = sobj;
//	// 派生类对象可以赋值给基类的对象 
//	Person pobj = sobj;
//	// 2.基类对象不能赋值给派生类对象，这里会编译报错 
//	//sobj = pobj;
//	// 3.支持基类对象指针(或引用)强制类型转换赋值给派生类对象指针或者引用
//	Student* ps = (Student*)pp;
//	Student& rs = (Student&)rp;
//	return 0;
//}
//class Person
//{
//protected:
//	string _name = "小梦";
//	int _id = 2004;
//};
//class Student :public Person
//{
//public:
//	void Print()
//	{
//		cout << "姓名：" << _name << endl;
//		cout << "身份证号：" << Person::_id << endl;
//		cout << "地址：" << _address << endl;
//		cout << "年龄：" << _age << endl;
//		cout << "学号：" << _id << endl;
//	}
//protected:
//	string _address = "SXIT";
//	int _age = 18;
//	int _id = 666;
//};
//struct A
//{
//	void Func() { cout << "void Func()" << endl; }
//};
//struct B :public A
//{
//	void Func(int i) { cout << "void Func(int i)" << endl; }
//};
//int main()
//{
//	B b;
//	b.Func(1);
//	b.A::Func();
//	return 0;
//}
//class Person
//{
//public:
//	Person(const char* name) :_name(name){ cout << "Person()" << endl; }
//	Person(const Person& p) :_name(p._name){ cout << "Person(const Person& p)" << endl; }
//	Person& operator=(const Person& p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//		return *this;
//	}
//	~Person() { cout << "~Person()" << endl; }
//protected:
//	string _name; // 姓名 
//};
//class Student : public Person
//{
//public:
//	Student(const char* name, int num):Person(name),_num(num) { cout << "Student()" << endl; }
//	Student(const Student& s) :Person(s) { cout << "Student(const Student& s)" << endl; }
//	Student& operator = (const Student& s)
//	{
//		cout << "Student& operator= (const Student& s)" << endl;
//		if (this != &s)
//		{
//			// 构成隐藏，所以需要显⽰调⽤ 
//			Person::operator =(s);
//			_num = s._num;
//		}
//		return *this;
//	}
//	~Student() { cout << "~Student()" << endl;}
//protected:
//	int _num; //学号 
//};
//int main()
//{
//	Student s1("jack", 18);
//	Student s2(s1);
//	Student s3("rose", 17);
//	s1 = s3;
//	return 0;
//}
//class A final
//{
//public:
//	A() { cout << "A()" << endl; }
//};
//class B :public A
//{
//protected:
//	int _a;
//};
//int main()
//{
//	B b;
//	return 0;
//}
//class Student;//前置声明
//class Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);
//protected:
//	string _name; // 姓名 
//};
//class Student : public Person
//{
//protected:
//	int _stuNum; // 学号 
//};
//void Display(const Person& p, const Student& s)
//{
//	cout << p._name << endl;
//	cout << s._stuNum << endl;
//}
//int main()
//{
//	Person p;
//    Student s;
//	// 编译报错：error C2248: “Student::_stuNum”: ⽆法访问 protected 成员 
//	// 解决⽅案：Display也变成Student 的友元即可 
//	Display(p, s);
//	return 0;
//}
//class Person
//{
//public:
//	string _name;
//	static int _count;
//};
//int Person::_count = 0;//静态成员必须类外初始化
//class Student : public Person
//{
//protected:
//	int _stuNum;
//};
//int main()
//{
//	Person p;
//	Student s;
//	// 这里的运行结果可以看到非静态成员_name的地址是不一样的 
//	// 说明派生类继承下来了，基类和派生类对象各有一份 
//	cout << &p._name << endl;
//	cout << &s._name << endl;
//	// 这里的运行结果可以看到静态成员_count的地址是一样的 
//	// 说明派生类和基类共用同一份静态成员 
//	cout << &p._count << endl;
//	cout << &s._count << endl;
//	// 公有的情况下，父或派生类指定类域都可以访问静态成员 
//	cout << Person::_count << endl;
//    cout << Student::_count << endl;
//	// ++影响的是同一个变量
//	++Person::_count;
//	cout << Person::_count << endl;
//	cout << Student::_count << endl;
//	++Student::_count;
//	cout << Person::_count << endl;
//	cout << Student::_count << endl;
//	return 0;
//}
//class Person
//{
//public:
//    string _name; // 姓名 
//};
//class Student : public Person
//{
//protected:
//	int _num; //学号 
//};
//class Teacher :  public Person
//{
//protected:
//	int _id; // 职⼯编号 
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程 
//};
//int main()
//{
//	// 编译报错：error C2385: 对“_name”的访问不明确 
//	Assistant a;
//	//a._name = "peter";
//	// 需要显⽰指定访问哪个基类的成员可以解决⼆义性问题，但是数据冗余问题⽆法解决 
//	a.Student::_name = "xxx";
//	a.Teacher::_name = "yyy";
//	cout << sizeof(Person) << endl;
//	cout << sizeof(Student) << endl;
//	cout << sizeof(Teacher) << endl;
//	cout << sizeof(Assistant) << endl;
//	return 0;
//}
//class Person
//{
//public:
//	string _name; // 姓名 
//};
//class Student :  public Person
//{
//protected:
//	int _num; //学号 
//};
//class Teacher :  public Person
//{
//protected:
//	int _id; // 职⼯编号 
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程 
//};
//int main()
//{
//	Assistant a;
//	cout << sizeof(Person) << endl;
//	cout << sizeof(Student) << endl;
//	cout << sizeof(Teacher) << endl;
//	cout << sizeof(Assistant) << endl;
//	return 0;
//}
// Tire(轮胎)和Car(⻋)更符合组合的关系 
//class Tire {
//protected:
//	string _brand = "Michelin"; // 品牌 
//	size_t _size = 17; // 尺寸 
//};
//class Car {
//protected:
//	string _colour = "白色"; // 颜色 
//	string _num = "陕ABIT00"; // ⻋牌号 
//	Tire _t1; // 轮胎 
//	Tire _t2; // 轮胎 
//	Tire _t3; // 轮胎 
//	Tire _t4; // 轮胎 
//};
//class BMW : public Car {
//public:
//	void Drive() { cout << "好开-操控" << endl; }
//};
//// Car和BMW/Benz更符合继承的关系 
//class Benz : public Car {
//public:
//	void Drive() { cout << "好坐-舒适" << endl; }
//};
//template<class T>
//class vector
//{};
//// stack和vector的关系，既符合is-a，也符合has-a 
//template<class T>
//class stack : public vector<T>
//{};
//template<class T>
//class stack
//{
//public:
//	vector<T> _v;
//};
//int main()
//{
//	return 0;
//}


// 7.多态的学习
#include<iostream>
using namespace std;
class Animal
{
public:
	virtual void say() const = 0;
};
class Dog :public Animal
{
public:
	virtual void say() const override final { cout << "旺旺" << endl; }
};
class Cat :public Animal
{
public:
	virtual void say() const override final { cout << "喵喵" << endl; }
};
void Func(Animal* a)
{
	a->say();
}
//int main()
//{
//	Dog d;
//	Cat c;
//	Func(&d);
//	Func(&c);
//	return 0;
//}
//struct Person
//{
//	virtual void BuyTicket() const { cout << "普通人全价购票" << endl; }//虚函数
//};
//struct Student :public Person
//{
//	virtual void BuyTicket() const { cout << "学生半价购票" << endl; }
//};
//void Func(Person* p)
//{
//	// 这里可以看到虽然都是Person指针Ptr在调用BuyTicket 
//    // 但是跟ptr没关系，而是由ptr指向的对象决定的。
//	p->BuyTicket();
//}
//void Func(Person& p)
//{
//	p.BuyTicket();
//}
//int main()
//{
//	Person p; Student s;
//	Func(p); Func(s);
//	return 0;
//}
//struct Person
//{
//	 void BuyTicket() const { cout << "普通人全价购票" << endl; }
//};
//struct Student :public Person
//{
//	 void BuyTicket() const { cout << "学生半价购票" << endl; }
//};
//void Func(Person& p)
//{
//	p.BuyTicket();
//}
//int main()
//{
//	Person p; Student s;
//	Func(p); Func(s);
//	return 0;
//}
//class A
//{
//public:
//	virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
//	virtual void test() { func(); }
//};
//class B : public A
//{
//public:
//	void func(int val = 0) { std::cout << "B->" << val << std::endl; }
//};
//
//int main()
//{
//	B* p = new B;
//	p->test();
//	return 0;
//}
//class A {};
//class B : public A {};
//class Person {
//public:
//	virtual A* BuyTicket()//只要求是基类的返回基类的指针或引用，并不要求是在同一继承体系中
//	{
//		cout << "买票-全价" << endl;
//		return nullptr;
//	}
//};
//class Student : public Person {
//public:
//	virtual B* BuyTicket()//同理
//	{
//		cout << "买票-打折" << endl;
//		return nullptr;
//	}
//};
//void Func(Person* ptr)
//{
//	ptr->BuyTicket();
//}
//int main()
//{
//	Person ps;
//	Student st;
//	Func(&ps);
//	Func(&st);
//    return 0;
//}
//class Car {
//public:
//	virtual void Dirve()
//	{}
//};
//class Benz :public Car {
//public:
//	// error C3668: “Benz::Drive”: 包含重写说明符“override”的⽅法没有重写任何基类⽅法 
//	virtual void Drive() override
//	{
//		cout << "Benz-舒适" << endl;
//	}
//};
//int main()
//{
//	return 0;
//}
//class Car
//{
//public:
//	virtual void Drive() final {}
//};
//class Benz :public Car
//{
//public:
//	// error C3248: “Car::Drive”: 声明为“final”的函数无法被“Benz::Drive”重写 
//	virtual void Drive() { cout << "Benz-舒适" << endl; }
//};
//int main()
//{
//	return 0;
//}
//class Car
//{
//public:
//	virtual void Drive() = 0;
//};
//class Benz :public Car
//{
//public:
//	virtual void Drive()
//	{
//		cout << "Benz-舒适" << endl;
//	}
//};
//class BMW :public Car
//{
//public:
//	virtual void Drive()
//	{
//		cout << "BMW-操控" << endl;
//	}
//};
//int main()
//{
//	// 编译报错：error C2259: “Car”: 无法实例化抽象类 
//	Car car;
//	Car* pBenz = new Benz;
//	pBenz->Drive();
//	Car* pBMW = new BMW;
//	pBMW->Drive();
//	return 0;
//}
class Base
{
public:
	virtual void Func1()
	{
		cout << "Func1()" << endl;
	}
protected:
	int _b = 1;
	char _ch = 'x';
};
int main()
{
	Base b;
	cout << sizeof(b) << endl;
	return 0;
}


// 8.list的学习
#include<iostream>
#include<list>
using namespace std;
template<class T>
void printf_container(const T& t)
{
	for (auto& e : t)
		cout << e << "-> ";
	cout << endl;
}
void test_construct()
{
	list<int> l1;                //空构造
	printf_container(l1);
	list<int> l2(4, 1);          //带参构造，构造4个结点值都为1
	printf_container(l2);
	list<int> l3(l2);            //用l2拷贝构造l3
	printf_container(l3);
	auto it = l3.begin();
	int k = 2;
	while (k--)
		++it;
	list<int> l4(l3.begin(), it);//用l3的一段迭代器区间去构造l4
	printf_container(l4);
	int arr[] = { 1,2,3,4 };
	list<int> l5(arr, arr + 4);  //用数组为迭代器区间构造l5
	printf_container(l5);
	list<int> l6 = { 6,7,8,9 };  //用列表初始化构造l6---C++11
	printf_container(l6);
}
void test_iterator()
{
	list<int> l1(4, 6);
	//普通正向迭代器遍历+修改
	list<int>::iterator it = l1.begin();
	while (it != l1.end())
	{
		*it += 2;
		++it;
	}
	printf_container(l1);
	//普通反向迭代器遍历+修改
	list<int>::reverse_iterator rit = l1.rbegin();
	while (rit != l1.rend())
	{
		*rit += 2;
		++rit;
	}
	printf_container(l1);
}
void test_capacity()
{
	list<int> l1;
	cout << l1.empty() << " " << l1.size() << endl;//判空和获取当前链表的有效结点个数(不包括哨兵位)
	list<int> l2(10, 1);
	cout << l2.empty() << " " << l2.size() << endl;
}
void test_element_access()
{
	list<int> l1(4, 1);
	printf_container(l1);
	l1.front() = 99; l1.back() = 66;//返回list的首或末节点中 值 的 引用
	printf_container(l1);
}
void test_modify()
{
	list<int> l1;
	l1.push_front(1); l1.push_front(2);//头插
	l1.push_front(3); l1.push_front(4);
	printf_container(l1);
	l1.pop_front();                   //头删
	printf_container(l1);
	list<int> l2;
	l2.push_back(5); l2.push_back(6);  //尾插
	l2.push_back(7); l2.push_back(8);
	printf_container(l2);
	l2.pop_back();                    //尾删
	printf_container(l2);
	int k = 2; auto it = l1.begin();
	while (k--)
		++it;
	l1.insert(it, 999);               //迭代器位置之前插入
	printf_container(l1);
	l1.erase(it);                     //删除迭代器位置结点
	printf_container(l1);
	cout << endl << endl;
	cout << "交换前" << endl;
	cout << "l1:"; printf_container(l1);
	cout << "l2:"; printf_container(l2);
	l1.swap(l2);                      //交换两个链表---实质交换底层两个链表的头结点
	cout << "交换后" << endl;
	cout << "l1:"; printf_container(l1);
	cout << "l2:"; printf_container(l2);
	l1.clear();                       //清理l1中有效元素
	cout << "l1:"; printf_container(l1);
}
int main()
{
	//test_construct();
	//test_iterator();
	//test_capacity();
	//test_element_access();
	test_modify();
	return 0;
}


// 9.stack和queue的学习
//#include<iostream>
//#include<stack>
//#include<queue>
//using namespace std;
//void test_stack()
//{
//	stack<int> s;
//	//s.top();
//	cout << s.size() << " " << s.empty() << endl;
//	s.push(1);s.push(2);
//	s.push(3);s.push(4);
//	cout << s.size() << " " << s.empty() << endl;
//	//cout<<s.top()<<" ";
//	//s.pop(); cout << s.top()<<" ";
//	//int arr[] = { 1,2,3,4,5 };
//	//stack<int> s2(arr, arr + 5);//只有编译器默认生成的构造函数，底层是deque，故也不需要实现stack的构造函数
//	stack<int> s3;
//	s3.emplace(1);s3.emplace(1);
//	s3.emplace(1);s3.emplace(1);
//	//while (!s3.empty())
//	//{
//	//	cout << s3.top() << " ";
//	//	s3.pop();
//	//}
//	s3.swap(s);
//	while (!s3.empty())
//	{
//		cout << s3.top() << " ";
//		s3.pop();
//	}
//	cout << endl;
//	while (!s.empty())
//	{
//		cout << s.top() << " ";
//		s.pop();
//	}
//}
//void test_queue()
//{
//	//queue<int> q(5,1);//也是如此，底层用了编译器自己默认生成的构造函数
//	queue<int> q;
//	cout << q.size() << " " << q.empty() << endl;
//	q.push(1);q.push(2);
//	q.push(3);q.push(4);
//	cout << q.size() << " " << q.empty() << endl;
//	while (!q.empty())
//	{
//		cout << q.front() << " ";
//		q.pop();
//	}
//	//int arr[] = { 1,2,3,4,5 };
//	//queue<int> q1(arr, arr + 5);//没有对应支持的构造函数
//	cout << endl;
//	queue<int> q2;
//	q2.emplace(1);q2.emplace(1);
//	q2.emplace(1);q2.emplace(1);
//	//while (!q2.empty())
//	//{
//	//	cout << q2.front() << " ";
//	//	q2.pop();
//	//}
//	q2.swap(q);
//	while (!q2.empty())
//	{
//		cout << q2.front() << " ";
//		q2.pop();
//	}
//	while (!q.empty())
//	{
//		cout << q.front() << " ";
//		q.pop();
//	}
//}
//void test_deque()
//{
//	deque<int> d1(5, 1);//底层可以看成是vector和list的缝合怪，自己也提供了构造函数的
//	for (auto& e : d1)
//		cout << e << " ";
//}
//int main()
//{
//	//test_stack();
//	//test_queue();
//	test_deque();
//	return 0;
//}
//priority_queue的学习
#include<queue>
int main()
{
	priority_queue<int> a;
	priority_queue<int, vector<int>, greater<int> > c;
	priority_queue<string> b;
	for (int i = 0; i < 5; i++)
	{
		a.push(i);
		c.push(i);
	}
	while (!a.empty())
	{
		cout << a.top() << ' ';
		a.pop();
	}
	cout << endl;
	while (!c.empty())
	{
		cout << c.top() << ' ';
		c.pop();
	}
	cout << endl;
	b.push("abc");
	b.push("abcd");
	b.push("cbd");
	while (!b.empty())
	{
		cout << b.top() << ' ';
		b.pop();
	}
	cout << endl;
	return 0;
}


// 10.模板进阶的学习
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
template<class T>//只有类型形参
T Add(const T& t1, const T& t2)
{
	return t1 + t2;
}
template<class T, size_t N = 10>//既有非类型也有类型形参
class Array1
{
public:
	T& operator[](size_t pos) { return a[pos]; }
	size_t size() { return N; }
private:
	T a[N];
};
#define N 10
template<class T>
class Array2
{
public:
	T& operator[](size_t pos) { return a[pos]; }
	size_t size() { return N; }
private:
	T a[N];
};
void test1()
{
	Array1<size_t, 20> a1;
	Array2<size_t> a2;
	cout << a1.size() << endl;//输出20
	cout << a2.size() << endl;//输出10
	Array1<size_t, 100> a3;
	Array2<size_t> a4;
	cout << a3.size() << endl;//输出100
	cout << a4.size() << endl;//输出10
}
//template<class T>//基础函数模板
//bool Less(T t1, T t2)
//{
//	return t1 < t2;
//}
//template<>//函数模板的特化
//bool Less<string*>(string* ps1, string* ps2)
//{
//	return *ps1 < *ps2;
//}
//bool Less(string* ps1, string* ps2)//具体给出，更推荐使用这种
//{
//	return *ps1 < *ps2;
//}
//void test2()
//{
//	string s1("hello");
//	string s2("abcde");
//	cout << Less(s1, s2) << endl;//预期输出0
//	string* ps1 = &s1;
//	string* ps2 = &s2;
//	cout << Less(ps1, ps2) << endl;//预期输出0
//}
template<class T1, class T2>//基础类模板
struct A
{
	A() { cout << "A<class T1, class T2>" << endl; }
	T1 a;
	T2 b;
};
template<>
struct A<int, char>//全特化
{
	A() { cout << "A<int, char>" << endl; }
	int a;
	char b;
};
void test3()
{
	A<double, double> a1;
	A<int, char> a2;
}
template<class T1, class T2, class T3>//基础类模板
struct B
{
	B() { cout << "B<class T1,class T2,class T3>" << endl; }
	T1 a;
	T2 b;
	T3 c;
};
template<class T1, class T3>
struct B<T1, int, T3>//偏特化的部分特化,只要第二个模板参数传int，就走这个,否则就走基础类模板
{
	B() { cout << "B<class T1, int ,class T3>" << endl; }
	T1 a;
	int b;
	T3 c;
};
void test4()
{
	B<double, double, double> b1;
	B<double, char, int> b2;
	B<double, int, double> b3;
	B<double, int, char> b4;
}
template<class T1, class T2>//基础类模板
struct C
{
	C() { cout << "C<class T1,class T2>  "; }
	T1 a;
	T2 b;
	void PrintType() { cout << typeid(T1).name() << " " << typeid(T2).name() << endl; }
};
template<class T1, class T2>
//偏特化的参数更进一步的限制---两个参数偏特化为指针类型
struct C<T1*, T2*>
{
	C() { cout << "C<T1*, T2*>  "; }
	T1 a;
	T2 b;
	void PrintType() { cout << typeid(T1).name() << " " << typeid(T2).name() << endl; }
};
template<class T1, class T2>
//偏特化的参数更进一步的限制---两个参数偏特化为引用类型
struct C<T1&, T2&>
{
	C() { cout << "C<T1&, T2&>  "; }
	T1 a;
	T2 b;
	void PrintType() { cout << typeid(T1).name() << " " << typeid(T2).name() << endl; }
};
void test5()
{
	C<double, double> c1; c1.PrintType();
	C<double*, double*> c2; c2.PrintType();
	C<double&, double&> c3; c3.PrintType();
}
struct Date
{
	friend ostream& operator<<(ostream& out, const Date& d);
	Date(int y = 0, int m = 0, int d = 0)
		:year(y), month(m), day(d) {}
	bool operator<(const Date& d)const
	{
		return (year < d.year)
			|| (year == d.year && month < d.month)
			|| (year == d.year && month == d.month && day < d.day);
	}
	int year; int month; int day;
};
ostream& operator<<(ostream& out, const Date& d)
{
	out << d.year << "-" << d.month << "-" << d.day;
	return out;
}
void Print(const vector<Date>& t)//打印Date类型
{
	for (auto& e : t)
		cout << e << endl;
}
void Print(const vector<Date*>& t)//打印Date*类型
{
	for (auto& e : t)
		cout << *e << endl;
}
template<class T>
struct Less
{
	bool operator()(const T x, const T y) const {
		return x < y;
	}
};
template<class T>
struct Less<T*>
{
	bool operator()(const T* x, const T* y) const
	{
		return *x < *y;
	}
};
void test6()
{
	Date d1(2022, 7, 7);
	Date d2(2022, 7, 6);
	Date d3(2022, 7, 8);
	vector<Date> v1;
	v1.push_back(d1); v1.push_back(d2); v1.push_back(d3);
	// 可以直接排序，结果是日期升序
	sort(v1.begin(), v1.end(), Less<Date>());
	Print(v1); cout << endl;
	vector<Date*> v2;
	v2.push_back(&d1); v2.push_back(&d2); v2.push_back(&d3);
	// 可以直接排序，结果错误日期还不是升序
	// 此处需要在排序过程中，让sort比较v2中存放地址指向的日期对象
	// 但是走Less模板，sort在排序时实际比较的是v2中指针的地址，因此无法达到预期
	sort(v2.begin(), v2.end(), Less<Date*>());
	Print(v2); cout << endl;
}
int main()
{
	//test1();
	//test2();
	//test3();
	//test4();
	//test5();
	test6();
	return 0;
}


// 11.map和set的学习
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
namespace test_set//set底层是红黑树,存储数据为一个key值，且不重复存储相同的key值，正向迭代器是中序遍历且默认为升序
{
	template<class set>
	void Print_Set(set& s)//
	{
		for (auto& e : s)
			cout << e << " ";
		cout << endl;
	}
	void test_construct()//构造
	{
		set<int> s1;//空构造
		Print_Set(s1);
		int arr[] = { 9,5,7,6,4,3,7,6,4,10,3 };
		set<int> s2(arr, arr + sizeof(arr) / sizeof(int));//迭代器区间构造
		Print_Set(s2);
		set<int> s3 = s2;//拷贝构造
		Print_Set(s3);
		set<int> s4 = { 6,2,6,7,1,10,3,4,9,0,8,2 };//列表构造
		Print_Set(s4);
		s1 = s2;//赋值重载
		Print_Set(s1);
	}
	void test_iterator()//迭代器---set是双向迭代器，只支持++，--
	{
		set<int> s1 = { 1,5,7,9,10,55,36,4,8,2,3 };
		//正向迭代器---输出升序
		//set<int>::iterator it=s1.begin();
		auto it = s1.begin();
		while (it != s1.end())
		{
			//*it += 2;        //set的普通迭代器都不支持修改key值
			//it += 2; it -= 2;//双向迭代器不支持+和-
			cout << *it << " ";
			++it;
		}
		cout << endl;
		//反向迭代器---输出降序
		//set<int>::reverse_iterator rit = s1.rbegin();
		auto rit = s1.rbegin();
		while (rit != s1.rend())
		{
			cout << *rit << " ";
			++rit;
		}
	}
	void test_modifiy()
	{
		//insert
		set<int> s1;
		//插入单个元素，返回类型为pair<iterator,bool>,如果已经存在则不会插入，并返回值中bool为false
		s1.insert(5);
		//检查插入
		int arr[] = { 1,9,8,7,5,4,2,1,3,0,9 };
		for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
		{
			if (s1.insert(arr[i]).second == false)
				cout << "插入失败，s1内已经有:" << arr[i] << endl;
			else cout << "插入成功" << endl;
		}
		Print_Set(s1); cout << endl;
		//列表插入，已经在容器中存在的值不会插入
		set<int> s2;
		s2.insert({ 1, 5, 9, 7, 3, 7 });
		Print_Set(s2);
		//迭代器区间插入
		set<int> s3;
		s3.insert(arr, arr + sizeof(arr) / sizeof(int));
		Print_Set(s3); cout << endl;
		//erase
		//删除⼀个迭代器位置的值,并返回原删除元素后一个元素位置的迭代器
		set<int> s4 = s3; Print_Set(s4);
		auto it = s4.erase(s4.begin());
		Print_Set(s4); cout << *it << endl;
		//删除val，返回删除元素的数量，对于set来说val不存在返回0，存在返回1 
		int i = 0;
		//while (cin >> i)
		//{
		//	if (s4.erase(i) == 0)
		//		cout << "s4中不存在该元素" << endl;
		//	else cout << "删除成功" << endl;
		//}
		Print_Set(s4);
		// 删除⼀段迭代器区间的值 
		set<int> s5 = s1; //Print_Set(s5);
		s5.erase(++s5.begin(), --s5.end()); //Print_Set(s5);
		// swap
		Print_Set(s5); Print_Set(s1);
		s5.swap(s1); Print_Set(s5); Print_Set(s1);
		// clear
		set<int> s6 = s5; Print_Set(s6);
		s6.clear(); Print_Set(s6);
	}
	void test_Operation()
	{
		int arr[] = { 9,5,7,6,6,3,2,0,10,1 };
		set<int> s1(arr, arr + sizeof(arr) / sizeof(int));
		//Print_Set(s1);
		// find---找到就返回该元素的迭代器，没有就返回end()
		// 用set的find时间为o(logN),是按二叉搜索树规则查找，用算法库则为o(N)，是按遍历查找
		//int i;
		//while (cin >> i)
		//{
		//	if (s1.find(i) == s1.end())
		//		cout << "s1中没有该元素" << endl;
		//	else cout << "查找成功" << endl;
		//}
		//查找+删除
		//while (cin >> i)
		//{
		//	if (s1.find(i) == s1.end())
		//		cout << "s1中没有该元素" << endl;
		//	else
		//	{
		//		s1.erase(i);
		//		cout << "删除成功" << endl;
		//		Print_Set(s1);
		//	}
		//}
		//算法库的查找---o(N) 
		//int i; cin >> i;
		//auto f = find(s1.begin(), s1.end(), i);
		//if (f != s1.end())
		//	cout << "查找成功" << endl;
		//else cout << "查找失败" << endl;
		// count(计数器)---返回某个元素的出现次数，在set中，只有0和1，为o(logN)
		// 利用count间接快速查找
		//int x; cin >> x;
		//if (s1.count(x))
		//	cout << "查找成功" << endl;
		//else cout << "查找失败" << endl;
		// 算法库---o(N)
		//int y; cin >> y;
		//if(count(s1.begin(),s1.end(),y))
		//	cout << "查找成功" << endl;
		//else cout << "查找失败" << endl;

		// lower_bound---返回大于等于val位置的迭代器
		// upper_bound---返回大于val位置的迭代器
		set<int> s2;
		for (int i = 0; i < 10; i++)
			s2.insert(i * 10);
		// 利用上述两个接口在s2中输出[45,75)区间内的所有数
		Print_Set(s2);
		auto it1 = s2.lower_bound(45);
		auto it2 = s2.upper_bound(75);
		while (it1 != it2)
		{
			cout << *it1 << " ";
			++it1;
		}
		it1 = s2.lower_bound(45);
		cout << endl;
		// 删除[55,95)区间内的所有数
		s2.erase(it1, it2); Print_Set(s2);
		// equal_range---返回相等元素的范围(pair<iterator,iterator>)---在set中用的不多，因为set是没有相等的元素
		auto p = s2.equal_range(0);
		s2.erase(p.first, p.second); Print_Set(s2);//删除所有的0，在set中大材小用，只删除一个0
	}
}
int main()
{
	//test_set::test_construct();
	//test_set::test_iterator();
	//test_set::test_modifiy();
	test_set::test_Operation();
	return 0;
}


// 12.课堂C++的学习(分组作业和报告)
#include<iostream>
using namespace std;
class Cuboid
{
public:
	Cuboid() {}//空构造，由于声明处给了默认参数，空构造后的值是默认参数的值
	Cuboid(double length, double width, double height)//这里都不给默认参数，因为全给了会与空构造造成调用歧义，也就是调用不到空构造
		:_length(length), _width(width), _height(height) {}//走初始化列表初始化所有成员
	void setter(double length, double width, double height)//setter方法设置值，一步到位的三个量都设置，虽然测试没调用，但有时需对原对象的三个值都进行修改
	{
		if (length <= 0 || width <= 0 || height <= 0)
		{
			cout << "长方体的长宽高中某个不合法，请重新输入" << endl;
			return;
		}
		_length = length;
		_width = width;
		_height = height;
	}
	void setterLength(double length)
	{
		if (length <= 0)
		{
			cout << "长不合法" << endl;
			return;
		}
		_length = length;
	}
	void setterWidth(double width)
	{
		if (width <= 0)
		{
			cout << "宽不合法" << endl;
			return;
		}
		_width = width;
	}
	void setterHeight(double height)
	{
		if (height <= 0)
		{
			cout << "高不合法" << endl;
			return;
		}
		_height = height;
	}
	double getter_length() const //获取长
	{
		return _length;
	}
	double getter_width() const //获取宽
	{
		return _width;
	}
	double getter_height() const //获取高
	{
		return _height;
	}
	double getArea() const //获取表面积
	{
		return 2 * (_length * _width + _length * _height + _width * _height);
	}
	double getCubage() const //获取体积
	{
		return _length * _width * _height;
	}
	void isCube() const //判断正方体
	{
		if (_length == _width && _width == _height && _length == _height)
			cout << "它是正方体" << endl;
		else
			cout << "它不是正方体" << endl;
	}
	void printCuboid() const
	{
		cout << "长方体的长为：" << _length << " 宽为：" << _width << " 高为：" << _height << endl;
	}
	void drawing() const
	{
		cout << "此长方体的各类信息如下：" << endl;
		printCuboid();
		cout << "表面积为：" << getArea() << endl;
		cout << "体积为：" << getCubage() << endl;
	}
private:
	double _length = 0;
	double _width = 0;
	double _height = 0;
};
void TestCuboid1()
{
	Cuboid cuboidA;//实例化对象，调用空构造
	cuboidA.setter(1.5, 2.6, 18.6);
	cuboidA.printCuboid();
	cuboidA.isCube();
	cuboidA.drawing();
}
void TestCuboid2()
{
	Cuboid cuboidB(2.5, 6.8, 8.0);//实例化对象,这里传参了，会去调用传参构造
	cout << "设置前";
	cuboidB.printCuboid();
	cuboidB.setterLength(4.6);
	cout << "设置后";
	cuboidB.printCuboid();
	cout << "设置后cuboidB的表面积为：" << cuboidB.getArea() << endl;
	cout << "设置后cuboidB的体积为：" << cuboidB.getCubage() << endl;
}
void Test()
{
	cout << "测试1：" << endl;
	TestCuboid1();
	cout << endl;
	cout << "测试2：" << endl;
	TestCuboid2();
}
//int main()
//{
//	Test();
//	return 0;
//}
class Car
{
public:
	Car(string brand = "", double emission = 0, double price = 0)//都给个默认参数
		:_brand(brand), _emission(emission), _price(price) {}
	string getBrand() const
	{
		return _brand;
	}
	void starting() const
	{
		cout << "此时启动了" << _brand << "的发动机！" << endl;
	}
private:
	string _brand = "";//C++11支持在声明变量位置给默认值(也叫缺省值)
	double _emission = 0;
	double _price = 0;
};
class Hand
{
public:
	Hand(string length = "", string area = "", string grip = "")
		:_length(length), _area(area), _grip(grip) {}
	void setter() {}; void getter() {};//题目要求省略这两个方法，这里就不给出具体的定义了
	void catching(const string& thing) const//传const引用更好一些
	{
		cout << "拿了" << thing;
	}
	void getInfo() const
	{
		cout << "手指长度为：" << _length
			<< "手掌面积为：" << _area
			<< "手的握力为：" << _grip;
	}
private:
	string _length = "";
	string _area = "";
	string _grip = "";
};
class Person
{
public:
	Person() {};
	Person(string id, string name, long long age, Hand& h)
		:_id(id), _name(name), _age(age), _h(h) {}
	string getName() const
	{
		return _name;
	}
	void showPerson() const
	{
		cout << "身份证号码为：" << _id
			<< "  名字叫：" << _name
			<< "  今年年龄为：" << _age << endl;
		_h.getInfo();
	}
	void saying(const Person& per, const string& msg) const//这里传const引用更好一些，首先我不会改变传入的值，其次可以减少调用拷贝构造，提升效率
	{
		cout << _name << "向" << per._name << "说：" << msg;
	}
	void getSomething(const string& something) const//照样用const引用
	{
		_h.catching(something);
	}
	void start(const Car& car) const
	{
		car.starting();
	}
private:
	string _id = "";
	string _name = "";
	long long _age = 0;
	Hand _h;//自己会去调用默认构造初始化
};
class TestDemo//奇奇怪怪，测试要求定义成类
{
public:
	void Test()
	{
		p1.saying(p2, "“八戒，你这个呆子！”");
		cout << "说完，孙悟空";
		p1.getSomething("一根金箍棒");
		cout << "并";
		p1.start(car);
		p1.saying(p2, "“八戒我去去就来”");
		cout << "说完，孙悟空";
		p1.getSomething("一根金箍棒");
		cout << "并";
		p1.start(car);
	}
private:
	Car car = { "红旗L5",3.0,250000 };
	Hand hand = { "8厘米","42平方厘米","45kg" };//Hand中有对应的构造函数即可这样初始化
	Person p1 = { "天庭特有id---88888888","孙悟空",LLONG_MAX,hand };//Person中有对应的构造函数即可用这种写法初始化
	Person p2 = { "天庭特有id---00000000","猪八戒",LLONG_MAX,hand };
};
int main()
{
	TestDemo t;
	t.Test();
	return 0;
}
class Room
{
public:
	Room() {}//空构造, 调用后我的程序会用声明处的默认参数进行初始化
	Room(string id, double area, int price)//编号，面积，单价的构造
		:_id(id), _area(area), _price(price) {}
	Room(string id, double area, string type, int price, bool state)//全构造
		:_id(id), _area(area), _type(type), _price(price), _state(state) {}
	void setterState(bool state)
	{
		_state = state;
	}
	void setterPrice(int price)
	{
		_price = price;
	}
	bool getterState() const
	{
		return _state;
	}
	double getterPrice() const
	{
		return _price;
	}
	double getArea() const
	{
		return _area;
	}
	void showRoom() const
	{
		cout << _id << "        " << _area << "           " << _type << "          " << _price;
		cout << "             ";
		if (_state == 0)
			cout << "false" << endl;
		else
			cout << "true" << endl;
	}
	//double getMoney(const Room* const this,Room& r2, Room& r3)----实际结构
	double getMoney(const Room& r2, const Room& r3) const//类里面有隐藏的this指针，其指向当前类对象
	{
		return this->_price + r2._price + r3._price;
	}
private:
	string _id = "";
	double _area = 0;
	string _type = "";
	double _price = 0;//虽然房间信息都为整型，但我还是设置成double
	bool _state = 0;
};
void showRoom(const Room& r1, const Room& r2, const Room& r3)//定义一个全局函数，用作统一展示
{
	cout << "-----------------------------------表6-1 楼盘river的房间信息-----------------------------------" << endl;
	cout << "编号id         " << "面积area         " << "户型type         " << "单价price         " << "销售状态state           " << endl;
	r1.showRoom(); r2.showRoom(); r3.showRoom();
}
void TestRoom()
{
	cout << "修改前：" << endl;
	Room r1("3-2-502 ", 113.5, "三室一厅", 15000, false);
	Room r2("4-5-1108", 156.9, "四室二厅", 17500, true);
	Room r3("4-3-1501", 45.9, " 二室一厅", 16200, true);
	showRoom(r1, r2, r3);
	cout << "三个房间的总面积为：" << r1.getArea() + r2.getArea() + r3.getArea() << endl;
	cout << "三个房间的总价为：" << r1.getMoney(r2, r3) << endl;
	cout << "修改后：" << endl;
	r1.setterState(true);
	showRoom(r1, r2, r3);
	cout << "三个房间的总面积为：" << r1.getArea() + r2.getArea() + r3.getArea() << endl;
	cout << "三个房间的总价为：" << r1.getMoney(r2, r3) << endl;
}
//int main()
//{
//	TestRoom();
//	return 0;
//}
//1.阶乘计算
unsigned long long get_factorial(int i)//计算阶乘的函数---但输入的数太大会超过其数值存储，导致后续结果出错
{
	//if (i == 0)
	//	return 1;
	//return i * get_factorial(i - 1);----递归写法可能会栈溢出
	unsigned long long  ret = 1;
	if (i == 0)//0!是1
		return 1;
	while (i)
	{
		ret *= i;
		i--;
	}
	return ret;
}
void Test1()
{
	int n;
	cout << "这是一个计算从0到该数的所有数的阶乘方法，现在请你输入一个数n：";
	cin >> n;
	for (int i = 0; i <= n; i++)
	{
		cout << i << "! =" << get_factorial(i) << endl;
	}
}
//2.利润计算
//法一：if else语句
void get_bonus1()
{
	cout << "请输入销售公司销售利润profit：";
	double profit = 0, bonus = 0;
	cin >> profit;
	if (profit < 0)
		cout << "您的输入似乎有点问题，您确认本公司今年利润小于0吗!" << endl;
	if (profit <= 100000)
		bonus = profit * 0.1;
	else if (profit <= 200000)
		bonus = 100000 * 0.1 + (profit - 100000) * 0.075;
	else if (profit <= 400000)
		bonus = 100000 * 0.1 + 100000 * 0.075 + (profit - 200000) * 0.05;
	else if (profit <= 600000)
		bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + (profit - 400000) * 0.03;
	else
		bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + 200000 * 0.03 + (profit - 600000) * 0.015;
	cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
}
//法二：switch语句
void get_bonus2()
{
	cout << "请输入销售公司销售利润profit：";
	double profit = 0; double bonus = 0;
	cin >> profit;
	if (profit == 0)
	{
		cout << "您可获得的个人奖金提成bonus为：0" << endl;
		return;
	}
	int _profit = profit; _profit /= 100000;//采取定义新变量来接受输入的值，用新变量去走switch语句，防止精度损失
	switch (_profit)
	{
	case 0:
		bonus = profit * 0.1;
		cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
		break;
	case 1:
		bonus = 100000 * 0.1 + (profit - 100000) * 0.075;
		cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
		break;
	case 2:
	case 3:
		bonus = 100000 * 0.1 + 100000 * 0.075 + (profit - 200000) * 0.05;
		cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
		break;
	case 4:
	case 5:
		bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + (profit - 400000) * 0.03;
		cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
		break;
	case 6:
	next:
		bonus = 100000 * 0.1 + 100000 * 0.075 + 200000 * 0.05 + 200000 * 0.03 + (profit - 600000) * 0.015;
		cout << "您可获得的个人奖金提成bonus为：" << bonus << endl;
		break;
	default:
		if (profit > 6)
			goto next;
		else cout << "您的输入似乎有点问题，您确认本公司今年利润小于0吗!" << endl;
		break;
	}
}
void Test2()
{
	get_bonus1();
	get_bonus2();
}
//int main()
//{
//	Test1();
//	Test2();
//	return 0;
//}
#include<iostream>
#include<string>
#include<cstdlib>
#include<Windows.h>
using namespace std;
void punishment()
{
	string input;
	system("shutdown -s -t 60");//包含头文件
	while (1)
	{
		cout << "由于您总是不按要求输入，现在将给予您一个小惩罚，您的电脑将在1分钟内自动关机，请注意这不是开玩笑";
		cout << "只要输入:（我错了）就可以终止关机！" << endl;
		cin >> input;
		if (strcmp(input.c_str(), "我错了") == 0)
		{
			system("shutdown -a");
			break;
		}
	}
	system("pause");
}
bool check(string& str)
{
	auto it = str.begin();
	int count = 3;
	while (it != str.end())
	{
		if ((*it >= '0' && *it <= '9') || (*it >= 'A' && *it <= 'Z') || (*it >= 'a' && *it <= 'z'))
			++it;
		else
		{
			--count;
			if (count == 0)
			{
				punishment();
				return false;
			}
			else
			{
				system("cls");
				cout << "您的输入有问题，请重新输入，您现在还有" << count << "次的输入机会" << endl;
				cout << "请认真对待，不然次数为0时会有惩罚" << endl;
				str.clear();
				cin >> str;
				it = str.begin();
			}
		}
	}
	return true;
}
// 加密算法
bool Encrypt(string& strProclaime)//简单的加密算法，要求只能输入大小写字母和阿拉伯数字
{                                 //对不按规则输入的，会进行检查并警告，警告三次后，依旧不正确输入会有小惩罚
	if (check(strProclaime) == 0)
	{
		cout << "惩罚结束，现在您可以选择继续运行程序去进行加密，注意：如果依旧不听话，照样会有惩罚！！！" << endl;
		return false;
	}
	system("cls");//进行加密的时候把原文在屏幕上清理掉
	cout << "加密进行中......." << endl;
	for (int i = 0; i < strProclaime.size(); i++)
	{
		Sleep(300);
		// 加密处理 0 - 9(ASCII中的48-57)
		if (strProclaime[i] >= '0' && strProclaime[i] <= '9')
			strProclaime[i] -= 14;
		// 加密处理 A- X(65-88)
		else if (strProclaime[i] >= 'A' && strProclaime[i] <= 'X')
			strProclaime[i] += 2;
		// 加密处理 a - x(97-120)
		else if (strProclaime[i] >= 'a' && strProclaime[i] <= 'x')
			strProclaime[i] += 2;
		// 加密处理 Y
		else if (strProclaime[i] == 'Y')
			strProclaime[i] = '!';
		// 加密处理 Z
		else if (strProclaime[i] == 'Z')
			strProclaime[i] = '?';
		// 加密处理 y
		else if (strProclaime[i] == 'y')
			strProclaime[i] = '^';
		// 加密处理 z
		else if (strProclaime[i] == 'z')
			strProclaime[i] = '@';
	}
	return true;
}
// 解密算法
void Decode(string& strCiphertext)//简单的加密算法，要求只能输入与之匹配的密文才能解密成功
{
	cout << "解密进行中......" << endl;
	for (int i = 0; i < strCiphertext.size(); i++)
	{
		Sleep(300);
		// 解密处理 " - +
		if (strCiphertext[i] >= '"' && strCiphertext[i] <= '+')
			strCiphertext[i] += 14;
		// 解密处理 C- Z(67-90)
		else if (strCiphertext[i] >= 'C' && strCiphertext[i] <= 'Z')
			strCiphertext[i] -= 2;
		// 解密处理 c - z(97-120)
		else if (strCiphertext[i] >= 'c' && strCiphertext[i] <= 'z')
			strCiphertext[i] -= 2;
		// 解密处理 !
		else if (strCiphertext[i] == '!')
			strCiphertext[i] = 'Y';
		// 解密处理 ?
		else if (strCiphertext[i] == '?')
			strCiphertext[i] = 'Z';
		// 解密处理 ^
		else if (strCiphertext[i] == '^')
			strCiphertext[i] = 'y';
		// 解密处理 @
		else if (strCiphertext[i] == '@')
			strCiphertext[i] = 'z';
	}
}
void menu()//特意写个菜单程序
{
	size_t input;
	string str;
	cout << "-----------------------------------------------这是一个简易的加密算法-----------------------------------------------" << endl;
	while (1)
	{
		cout << "-----------------------------------------------请选择您要进行的操作(数字即可):--------------------------------------" << endl;
		cout << "               0.退出                     1.加密                                  2.解密                     " << endl;
		cin >> input;
		switch (input)
		{
		case 0:
			cout << "退出成功" << endl;
			return;
		case 1:
			cout << "正在进行加密......" << endl;
			cout << "请输入明文，明文的输入范围是:任意的大小写字母和阿拉伯数字" << endl;
			cout << "输入的注意事项:您必须按输入范围要求去输入，总共有三次的输入机会，如果一直不按要求输入将会有小惩罚哦！" << endl;
			cin >> str;
			if (Encrypt(str) == 0)
				break;
			cout << "加密后的密文为:" << str << endl;
			break;
		case 2:
			cout << "正在进行解密......" << endl;
			cout << "请输入经此加密算法加密的内容，要认真输入哦，小心也有惩罚" << endl;
			cin >> str;
			Decode(str);//解密算法内部没有进行对应检查，检查也可以，也就是同样的逻辑，但会增加代码长度，实验报告装不下，所以我不写
			cout << "解密后的密文为:" << str << endl;
			break;
		default:
			system("cls");
			cout << "系统不知道您要干什么，请重新输入" << endl;
			break;
		}
	}
}
//int main()
//{
//	menu();
//	return 0;
//}
#include<iostream>
#include<string>
using namespace std;
class Student
{
	friend istream& operator>>(istream& in, Student& s);
	friend ostream& operator<<(ostream& out, Student& s);
public:
	void cheak() const//一个检查函数，检查输入数据是否合法(只检测学号和性别)
	{
		if (_id <= 0)//认为id必须>0
		{
			cout << "输入学号不合法，请重新输入" << endl;
			return;
		}
		if (strcmp(_gender.c_str(), "female") != 0 && strcmp(_gender.c_str(), "male") != 0)//认为性别非男即女
		{
			cout << "输入性别不合法，请重新输入" << endl;
			return;
		}
	}
	//实验要求构造函数走声明与定义分离
	Student(int id, string name, string gender);//初始化前三个的带参数构造函数---类内声明
	Student(string date, string class1, string profession = "数据科学与大数据技术");//初始化后三个的半缺省构造函数
	Student(int id = INT_MAX, string name = "", string gender = "male", string date = "", string class1 = "2班", string profession = "计算机科学与技术");//全缺省构造(也是默认构造函数)
	void SetInfo(int id, string name, string gender, string date, string class1, string profession)//修改时要求统一传入修改后的全部信息
	{
		_id = id; _name = name; _gender = gender;
		_date = date; _class1 = class1; _profession = profession;
		cheak();
	}
	void Show() const
	{
		cout << _id
			<< "      " << _name
			<< "         " << _gender
			<< "          " << _date
			<< "          " << _grade
			<< "          " << _class1
			<< "          " << _department
			<< "          " << _profession
			<< endl;
	}
private://所定义的成员变量形式是按照实验参考上的数据来的,认为操作的学生对象是同一院系，同一年级的
	int _id = INT_MAX;              //学号
	string _name;                   //姓名
	string _gender;                 //性别
	string _date;                   //出生日期
	static const string _grade;     //年级
	string _class1;                 //班级
	static const string _department;//院系
	string _profession;             //专业
};
const string Student::_grade = "05 级";//静态成员类外初始化
const string Student::_department = "computer ";
Student::Student(int id, string name, string gender)//类外定义
	:_id(id), _name(name), _gender(gender) {
	Student::cheak();//构造函数内部进行输入数据合法性检查
}
Student::Student(int id, string name, string gender, string date, string class1, string profession)//类外定义不要加缺省值
	: _id(id), _name(name), _gender(gender), _date(date), _class1(class1), _profession(profession) {
	Student::cheak();
}
Student::Student(string date, string class1, string profession)
	:_date(date), _class1(class1), _profession(profession) {
	Student::cheak();
}
void Show()//补充一个全局函数，方便展示清楚
{
	cout << "-----------------------------------------------------------学生的数据-----------------------------------------------------------" << endl;
	cout << "学号          姓名             性别            出生日期             年级           班级             院系              专业" << endl;
}
istream& operator>>(istream& in, Student& s)//重载一个流插入
{
	in >> s._id; in >> s._name; in >> s._gender;
	in >> s._date; in >> s._class1; in >> s._profession;
	return in;
}
ostream& operator<<(ostream& out, Student& s)//重载一个流提取
{
	printf("%d", s._id);//这里试试格式化的输出
	printf("%13s", s._name.c_str());//自己挑出来的对齐参数
	printf("%15s", s._gender.c_str());
	printf("%20s", s._date.c_str());
	printf("%17s", s._grade.c_str());
	printf("%16s", s._class1.c_str());
	printf("%21s", s._department.c_str());
	printf("%18s", s._profession.c_str());
	return out;
}
void Test()
{
	cout << "这是不自己输入的结果：" << endl;
	Student s1(2005001, "zhangesan", "male", "  85年11月   ", "jy01", "application");//输入时进行增补空格处理，输出的表格好看些
	Student s2(2005002, "lihua    ", "female", "84年11月   ", "jy01", "application");//也可以输出表格时考虑用格式化的输入函数printf
	Student s3(2005003, "wang     ", "male", "  85年7月    ", "jy01", "software");
	Student s4(2005004, "zhan     ", "male", "  85年11月   ", "jy02", "application");
	Student s5(2005005, "song     ", "female", "85年11月   ", "jy03", "software");
	Show();
	s1.Show(); s2.Show();
	s3.Show(); s4.Show(); s5.Show();
	//但报告要求用对象数组进行保存---这里程序设计只把测试数据保留下来，即开辟固定的数组大小
	cout << endl << endl;
	cout << "请依次输入要存入对象数组中的每个对象的值" << endl;
	Student* S = new Student[5];//会调用默认构造函数初始化
	for (int i = 0; i < 5; i++)
	{
		//cout << "即输入第"<<i+1<<"个同学的学号，姓名，性别，出生日期，班级和专业" << endl;
		cin >> S[i];
	}
	cout << endl;
	cout << "这是自己输入的结果：" << endl;
	Show();
	for (int i = 0; i < 5; i++)
		//S[i].show();//这里就不调用show了，调用show时输入会很麻烦，不如重载一个流提取
		cout << S[i] << endl;
	delete[] S;
}
//int main()
//{
//	Test();
//	return 0;
//}
#include<iostream>
#include<string>
using namespace std;
class Person//雇员类
{
public:
	void Scanf()
	{
		cout << "请依次输入信息：" << endl;
		cout << "代号："; cin >> id;
		cout << "年龄："; cin >> age;
		cout << "基本工资："; cin >> money;
		cout << "性别："; cin >> gender;
		cout << "名字："; cin >> name;
	}
	void Print() const
	{
		cout << "代号： " << id
			<< "  年龄： " << age
			<< "  工资： " << money
			<< "  性别： " << gender
			<< "  名字： " << name << endl;
	}
protected:
	int id = INT_MAX;//自己走系统生成的默认构造初始化
	int age = INT_MAX;
	int money = INT_MAX;//基本工资
	string gender = "male";//报告上用字符数组确实更省空间,但我不用
	string name = "帅明";
};
class Teacher :public Person//教师
{
public:
	Teacher()
	{
		Person::Scanf();//调用基类的输入函数进行初始化
		cout << "请输入教师的课时量：" << endl;
		cin >> hour;
	}
	void Sum()
	{
		money += hour * 30;//工资
		//cout << "教师的工资为：" << money;
	}
protected:
	int hour = INT_MAX;//课时
};
class Experiment :public Person
{
public:
	Experiment()
	{
		Person::Scanf();
		cout << "请输入实验人员的值班时间：" << endl;
		cin >> hour;
		cout << "请输入实验人员的补助：" << endl;//不给出固定值，用户想输入多少就多少
		cin >> subsidy;
	}
	void Sum()
	{
		money += (subsidy + hour * 5);
	}
protected:
	int hour = INT_MAX;//值班时间
	int subsidy = INT_MAX;//实验室补助
};
class Politicser :public Person
{
public:
	Politicser()
	{
		Person::Scanf();
		cout << "请输入行政人员的补助：" << endl;
		cin >> subsidy;
	}
	void Sum()
	{
		money += subsidy;
	}
protected:
	int subsidy = INT_MAX;//行政补助
};
void test()
{
	Teacher t;
	Experiment e;
	Politicser p;
	cout << "这是老师的信息：" << endl;
	t.Sum(); t.Print();
	cout << "这是实验人员的信息：" << endl;
	e.Sum(); e.Print();
	cout << "这是行政人员的信息：" << endl;
	p.Sum(); p.Print();
}
//int main()
//{
//	test();
//	return 0;
//}
#include<iostream>
using namespace std;
class Vehicle//基类---车类---抽象类
{
public:
	Vehicle(const char* c, const char* n, const char* d)//这些信息认为一旦输入后就不允许随意更改
		:carname(c), name(n), date(d) {}
	virtual void show() const = 0;//纯虚函数，认为车类是个大类，不能衍生具体事物
protected:
	const char* carname;//车名---确实字符指针要好些，就不去使用string了
	const char* name;   //车主名
	const char* date;   //购买日期
};
class Car :public Vehicle
{
public:
	Car(const char* c, const char* n, const char* d, size_t z)
		:Vehicle(c, n, d), zws(z) {}//基类部分调用基类的构造函数初始化
	//实现多态的条件，对基类的虚函数进行重写
	virtual void show() const override//virtual也可以不加，为了程序易读还是加上
	{                           //加入override表示对基类虚函数重写进行检查
		cout << name << "的"
			<< carname << "(小汽车),购买于"
			<< date << "，其座位数为"
			<< zws << "(单位：个)" << endl;
	}
protected:
	size_t zws;//座位数
};
class Truck :public Vehicle
{
public:
	Truck(const char* c, const char* n, const char* d, double dw)
		:Vehicle(c, n, d), _dw(dw) {}
	virtual void show() const override
	{
		cout << name << "的"
			<< carname << "(货车),购买于"
			<< date << ",其吨位为"
			<< _dw << "(单位：吨)" << endl;
	}
protected:
	double _dw;//吨位
};
void test_polymorphic()
{
	Car A("Benz", "shuaiming", "2024-11-17", 2);//豪华双人座的跑车
	Truck B("Dongfeng", "shuaimingabc", "2024-11-17", 5.5);
	//多态的两种实现形式：
	//1.指针
	cout << "1.指针调用多态:" << endl;
	Vehicle* pA, * pB;
	pA = &A; pB = &B;
	pA->show(); pB->show();
	cout << endl << endl;
	//2.引用
	cout << "2.引用调用多态:" << endl;
	Vehicle& rA = A, & rB = B;//定义时必须初始化
	rA.show(); rB.show();
}
int main()
{
	test_polymorphic();
	return 0;
}
#include<iostream>
using namespace std;
void meun1()//if else
{
	char input;
	while (1)
	{
		cout << "---------------------------请选择您要进行的操作(字母即可):---------------------------" << endl;
		cout << "------------------------A(Add)                       D(Delete------------------------" << endl;
		cout << "------------------------S(Sort)                      Q(Quit)-------------------------" << endl;
		cin >> input;
		if (input == 'A')
			cout << "数据已经增加" << endl;
		else if (input == 'D')
			cout << "数据已经删除" << endl;
		else if (input == 'S')
			cout << "数据已经排序" << endl;
		else if (input == 'Q')
		{
			cout << "程序已经结束" << endl;
			break;
		}
		else cout << "并没有此操作呢，请重新输入试试!" << endl;
	}
}
void meun2()//switch
{
	char input;
	while (1)
	{
		cout << "---------------------------请选择您要进行的操作(字母即可):---------------------------" << endl;
		cout << "------------------------A(Add)                       D(Delete------------------------" << endl;
		cout << "------------------------S(Sort)                      Q(Quit)-------------------------" << endl;
		cin >> input;
		switch (input)
		{
		case 'A':
			cout << "数据已经增加" << endl;
			break;
		case 'D':
			cout << "数据已经删除" << endl;
			break;
		case 'S':
			cout << "数据已经排序" << endl;
			break;
		case 'Q':
			cout << "程序已经结束" << endl;
			return;
		default:
			cout << "并没有此操作呢，请重新输入试试!!!" << endl;
			break;
		}
	}
}
//int main()
//{
//	meun1();
//	//meun2();
//	return 0;
//}
//class A
//{
//public:
//	A()  {	 cout << "A()" << endl;  }
//};
//class B
//{
//public:
//	B()  {	cout << "B()" << endl;   }
//};
//class C :public A
//{
//public:
//	C()  {	 cout << "C()" << endl;  }
//protected:
//	B b;
//};
//int main()
//{
//	C c;
//	return 0;
//}
struct B
{
	B() { cout << "B()" << endl; }
};
struct A
{
	A() { cout << "A()" << endl; }
};
struct E
{
	E() { cout << "E()" << endl; }
};
struct D
{
	D() { cout << "D()" << endl; }
};
struct BB
{
	BB() { cout << "BB()" << endl; }
};
struct C :BB, A, B
{
	C() { cout << "C()" << endl; }
protected:
	D _e;
	E _d;
};
int main()
{
	C c;
	return 0;
}


// C++练习题
// 1.求1+2+3+...+n，要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句（A?B:C)
https://www.nowcoder.com/practice/7a0da8fc483247ff8800059e12d7caf1?tpId=13&tqId=11200&tPage=3&rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
//法一：
//定义两个类，利用static成员变量和static成员函数的特性，
//实例化n个对象，每个对象都会调用构造函数，在构造函数内实现累加
class Sum {
public:
	Sum() {
		_sum += _i;
		++_i;
	}
	static int get() {
		return _sum;
	}
private:
	static int _i;
	static int _sum;
};
int Sum::_i = 1;
int Sum::_sum = 0;
class Solution {
public:
	int Sum_Solution(int n) {
		Sum a[n];
		//Sum* a=new Sum[n]  --->也行
		return Sum::get();
	}
};
//法二：
//内部类
class Solution {
private:
	static int _i;
	static int _sum;
	class Sum {//内部类
	public:
		Sum() {
			_sum += _i;
			++_i;
		}
	};
public:
	int Sum_Solution(int n) {
		Sum a[n];
		//Sum* a=new Sum[n]  --->也行
		return _sum;
	}
};
int Solution::_i = 1;
int Solution::_sum = 0;

// 2.计算一年的第几天
https://www.nowcoder.com/practice/769d45d455fe40b385ba32f97e7bcded?tpId=37&&tqId=21296&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
int main() {
	int year, month, day;
	const int ArrayMonth[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	cin >> year >> month >> day;
	int sum = 0;
	for (int i = 1; i < month; i++) {
		if (i == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
			sum += 29;
		else sum += ArrayMonth[i];
	}
	sum += day;
	cout << sum << endl;
	return 0;
}

// 3.日期差值
////https://www.nowcoder.com/practice/ccb7383c76fc48d2bbc27a2a6319631c?tpId=62&&tqId=29468&rp=1&ru=/activity/oj&qru=/ta/sju-kaoyan/question-ranking
////法一：用日期类做题
//#include <iostream>
//using namespace std;
//class Date {
//public:
//    Date(int year, int month, int day)
//        : _year(year), _month(month), _day(day) {}
//    int get_month_day(int year, int month) {
//        static int ArrayMonth[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
//            return 29;
//        else
//            return ArrayMonth[month];
//    }
//    bool operator<(Date& d) {
//        if (_year < d._year)
//            return true;
//        else if (_year == d._year) {
//            if (_month < d._month)
//                return true;
//            else if (_month == d._month) {
//                if (_day < d._day)
//                    return true;;
//            }
//        }
//        return false;
//    }
//    Date& operator++() {
//        _day += 1;
//        if (_day > get_month_day(_year, _month)) {
//            _day -= get_month_day(_year, _month);
//            ++_month;
//            if (_month > 12) {
//                _month = 1;
//                ++_year;
//            }
//        }
//        return *this;
//    }
//    int operator-(Date& d) {
//        int flag = 1, ret = 0;
//        Date min = *this;
//        Date max = d;
//        if (d < *this) {
//            min = d;
//            max = *this;
//            flag = -1;
//        }
//        while (min < max) {
//            ++min;
//            ++ret;
//        }
//        return (ret + 1) * flag;
//    }
//private:
//    int _year;
//    int _month;
//    int _day;
//};
//int main() {
//    int n1;
//    cin >> n1;
//    int n2;
//    cin >> n2;
//    int year1 = n1 / 10000, month1 = (n1 % 10000) / 100, day1 = n1 % 100;
//    int year2 = n2 / 10000, month2 = (n2 % 10000) / 100, day2 = n2 % 100;
//    Date d1(year1, month1, day1);
//    Date d2(year2, month2, day2);
//    cout << (d1 - d2) << endl;
//    return 0;
//}
////法二：
///*
//  *思路：
//  * 1. 分别求出每一个日期与0000年0月1日距离的天数
//  * 2. 两个距离天数相减即可得到两个日期相差的天数
//  */
//  //平年从1月到n月的天数
//int mon[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
////给出年月日，计算距离0000年0月1日的天数和
//int CountDay(int y, int m, int d)
//{
//    // 计算0-y年的天数
//    int yearDay = y * 365 + y / 4 - y / 100 + y / 400;
//    // 计算到0-m月的天数
//    int monthDay = mon[m - 1];
//    if (m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0))
//        monthDay += 1;
//    return yearDay + monthDay + d;
//}
//int main()
//{
//    int year1, month1, day1;
//    scanf("%4d%2d%2d", &year1, &month1, &day1);
//    int n1 = CountDay(year1, month1, day1);
//    int year2, month2, day2;
//    scanf("%4d%2d%2d", &year2, &month2, &day2);
//    int n2 = CountDay(year2, month2, day2);
//    cout << abs(n1 - n2) + 1 << endl;
//}
// 4.累加天数
//https://www.nowcoder.com/practice/eebb2983b7bf40408a1360efb33f9e5d?tpId=40&&tqId=31013&rp=1&ru=/activity/oj&qru=/ta/kaoyan/question-ranking
//#include <iostream>
//using namespace std;
//int get_month_day(int year, int month)
//{
//    int ArrayMonth[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };
//    if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
//        return 29;
//    else return ArrayMonth[month];
//}
//void AfterSum(int year, int month, int day, int n)
//{
//    day += n;
//    while (day > get_month_day(year, month))
//    {
//        day -= get_month_day(year, month);
//        month++;
//        if (month == 13)
//        {
//            month = 1;
//            ++year;
//        }
//    }
//    printf("%04d-%02d-%02d\n", year, month, day);//用C中格式化输出
//}
//int main() {
//    int m; cin >> m;
//    while (m--)
//    {
//        int year, month, day, n; cin >> year >> month >> day >> n;
//        AfterSum(year, month, day, n);
//    }
//    return 0;
//}

// 5.打印日期
//https://www.nowcoder.com/practice/b1f7a77416194fd3abd63737cdfcf82b?tpId=69&&tqId=29669&rp=1&ru=/activity/oj&qru=/ta/hust-kaoyan/question-ranking
#include <iostream>
using namespace std;
bool is_run_year(int m) {
	if ((m % 4 == 0 && m % 100 != 0) || m % 400 == 0)
		return true;
	else return false;
}
void Print(int m, int n) {
	if ((n == 366 && is_run_year(m)) || (n == 365 && !(is_run_year(m))))
	{
		printf("%04d-%02d-%02d\n", m + 1, 1, 1);
		return;
	}
	int get_month_day[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (((m % 4 == 0 && m % 100 != 0) || m % 400 == 0))
		get_month_day[2] = 29;
	int ret = 0;
	for (int i = 1; i <= 12; i++) {
		n -= get_month_day[i];
		if (n <= 0) {
			n += get_month_day[i];
			ret = i;
			break;
		}
	}
	printf("%04d-%02d-%02d\n", m, ret, n);
}
int main() {
	int m, n;
	while (cin >> m >> n) {
		Print(m, n);
	}
	return 0;
}

// 6.字符串转整形数字
// https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/
int myAtoi(char* s) {
	long long num = 0;
	int i = 0, flag = 1;
	int size = strlen(s);
	// 跳过前导空格
	while (i < size && s[i] == ' ')
		i++;
	if (s[i] == '-') {
		flag = -1;
		i++;
	}
	else if (s[i] == '+')
		i++;
	for (; i < size; i++) {
		char c = s[i];
		if (c < '0' || c > '9')
			break;
		num = num * 10 + (c - '0');
		long long v = num * flag;
		if (v > INT_MAX)
			return INT_MAX;
		if (v < INT_MIN)
			return INT_MIN;
	}
	return num * flag;
}
// 7.翻转字符串 https://leetcode.cn/problems/reverse-string/
class Solution {
public:
	void reverseString(vector<char>& s) {
		int begin = 0, end = s.size() - 1;
		while (begin < end) {
			swap(s[begin++], s[end--]);
		}
	}
};
// 8.判断字符串是否回文
https://leetcode.cn/problems/valid-palindrome/
class Solution {
public:
	bool isPalindrome(string s) {
		if (s == " ")
			return true;
		int i = 0, size = s.size();
		while (i < size) // 此循环目的是把s中的大写转化为小写，并把非数字字母的内容删除掉
		{
			if (s[i] >= 'A' && s[i] <= 'Z')
				s[i++] += 32;
			else if ((s[i] >= 'a' && s[i] <= 'z') ||
				(s[i] >= '0' && s[i] <= '9')) {
				++i;
				continue;
			}
			else {
				s.erase(i, 1);
				--size;
			}
		}
		int begin = 0, end = s.size() - 1;
		while (begin < end) //双指针
		{
			if (s[begin] != s[end])
				return false;
			++begin;
			--end;
		}
		return true;
	}
};
// 9.字符串里面最后一个单词的长度
//https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da?tpId=37&&tqId=21224&rp=5&ru=/activity/oj&qru=/ta/huawei/question-ranking
int main() {
	string s;
	getline(cin, s);
	reverse(s.begin(), s.end());
	int i = 0, count = 0;
	while (s[i] != ' ' && i < s.size()) {
		count++;
		i++;
	}
	cout << count;
}
class Solution {
public:
	// 10.杨辉三角
	//https://leetcode.cn/problems/pascals-triangle/
	vector<vector<int>> generate(int numRows) {
		vector<vector<int>> vv(numRows);
		for (int i = 0; i < numRows; i++) {
			vv[i].resize(i + 1, 1);
		}
		for (int i = 2; i < numRows; i++) {
			for (int j = 1; j < vv[i].size() - 1; j++) {
				vv[i][j] = vv[i - 1][j - 1] + vv[i - 1][j];
			}
		}
		return vv;
	}
	// 11.反转字符串中的单词
	//https://leetcode.cn/problems/reverse-words-in-a-string-iii/
	string reverseWords(string s) {
		size_t n = s.size();
		auto it = s.begin();
		auto rit = s.begin();
		for (size_t i = 0; i < n; i++) {
			if (s[i] == ' ') {
				reverse(it, rit);
				it = rit + 1;
			}
			++rit;
		}
		reverse(it, s.end());
		return s;
	}
	// 12.字符串中第一个唯一的字符
	//https://leetcode.cn/problems/first-unique-character-in-a-string/
	int firstUniqChar(string s) {
		int arr[26] = { 0 };
		for (int i = 0; i < s.size(); i++) {
			arr[s[i] - 'a'] += 1;
		}
		for (int i = 0; i < s.size(); i++) {
			if (arr[s[i] - 'a'] == 1)
				return i;
		}
		return -1;
	}
};

// 13.实现string类的接口，并完成测试，要求利用深拷贝和深赋值实现
#include<iostream>
#include<string>
using namespace std;
using std::cout;
using std::endl;
//class string
//{
//public:
//	string(const char* str = "")
//	{
//		size_t n = strlen(str);
//		_str = new char[n + 1];
//		for (size_t i = 0; i < n; i++)
//		{
//			_str[i] = str[i];
//		}
//		_str[n] = '\0';
//	}
//	string(const string& s)
//	{
//		size_t n = strlen(s._str);
//		_str = new char[n + 1];
//		for (size_t i = 0; i < n; i++)
//		{
//			_str[i] = s._str[i];
//		}
//		_str[n] = '\0';
//	}
//	string& operator=(const string& s)
//	{
//		if (s._str != this->_str)// 避免自我赋值
//		{
//			size_t n = strlen(s._str);
//			char* tmp = new char[n + 1];
//			for (size_t i = 0; i < n; i++)
//			{
//				tmp[i] = s._str[i];
//			}
//			tmp[n] = '\0';
//			delete[] _str;
//			_str = tmp;
//		}
//		return *this;
//	}
//	~string()
//	{
//		if (_str)
//			delete[] _str;
//		_str = nullptr;
//	}
//	void Print()
//	{
//		size_t n = strlen(_str);
//		for (size_t i = 0; i < n; i++)
//		{
//			cout << _str[i];
//		}
//		cout << endl;
//	}
//private:
//	char* _str;
//};
//void test()
//{
//	string s1;
//	s1.Print();
//	string s2("hello world");
//	s2.Print();
//	string s3(s2);
//	s2.Print();
//	s1 = s2;
//	s1.Print();
//}
//int main()
//{
//	test();
//	return 0;
//}

// 14.翻转字符串II：区间部分翻转
//https://leetcode.cn/problems/reverse-string-ii/
string reverseStr(string s, int k) {
	size_t n = s.size();
	for (int i = 0; i < s.size(); i += 2 * k) {
		if (n - i < k) {
			reverse(s.begin() + i, s.end());
			return s;
		}
		if (n - i < 2 * k && s.size() >= k) {
			reverse(s.begin() + i, s.begin() + k + i);
			return s;
		}
		if (i + k < n)
			reverse(s.begin() + i, s.begin() + i + k);
	}
	return s;
}
#include<iostream>
#include<vector>
using namespace std;
// 15.删除有序数组中的重复项
//https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ 
//法一：调用erase方法
int removeDuplicates(vector<int>& nums) {
	int n = nums.size();
	auto it = nums.begin() + 1;
	while (it != nums.end())
	{
		if (it != nums.end() && *it == *(it - 1)) {
			it = nums.erase(it);
			--n;
		}
		else
			++it;
	}
	return n;
}
//法二：数组原地对应虚拟开辟数组(就是原数组本身),快慢指针，每次快指针遇到不同于慢指针的数时就进行赋值
int removeDuplicates(vector<int>& nums) {
	int j = 0;
	for (int i = 1; i < nums.size(); i++) {
		if (nums[j] != nums[i]) {
			j++;
			nums[j] = nums[i];
		}
	}
	return j + 1;
}
// 16.数组中出现次数超过一半的数字
//https://www.nowcoder.com/share/jump/3141631241734938471164 
//法一：面向结果的编程---类似计数排序
int MoreThanHalfNum_Solution(vector<int>& numbers) {
	int arr[10001] = { 0 };
	int n = numbers.size() / 2;
	for (int i = 0; i < numbers.size(); i++) {
		arr[numbers[i]]++;
	}
	for (int i = 0; i < 10000; i++) {
		if (arr[i] > n)
			n = i;
	}
	return n;
}
//法二：候选人法---假定数组中第一个数 cond 就是要找的数(候选人),初始计数 cnt 为1(票数)
//通过遍历数组，如果遇到与初始cond相同的数就增加cnt(票数),反之则减一票数
//如果票数归零，就选当前对应数为候选人，继续遍历重复上述操作，直至遍历完数组
//最后检查：先置票数为0，再遍历数组对选定的候选人进行统计票数，统计后检查票数是否大于数组长度的一半，
//大于就返回，反之返回0，表示没有这样的数(候选人)
int MoreThanHalfNum_Solution(vector<int> numbers) {
	int cond = -1;//候选人
	int cnt = 0;//票数
	for (int i = 0; i < numbers.size(); ++i) {
		if (cnt == 0) {//票数为0就重选候选人
			cond = numbers[i];
			++cnt;
		}
		else {
			if (cond == numbers[i]) ++cnt;//遇到相同数就加一票数
			else --cnt;//反之则减一票数
		}
	}
	cnt = 0;
	for (const int k : numbers) {
		if (cond == k) ++cnt;//统计票数
	}
	if (cnt > numbers.size() / 2) return cond;//检查票数是否大于一半
	return 0;
}
// 17. https://leetcode.cn/problems/min-stack/ 最小栈
class MinStack {
public:
	MinStack() = default;

	void push(int val) {
		_st.push(val);
		if (_minst.empty() || _minst.top() >= val)
			_minst.push(val);
	}

	void pop() {
		if (_st.top() == _minst.top()) {
			_st.pop();
			_minst.pop();
		}
		else
			_st.pop();
	}

	int top() { return _st.top(); }

	int getMin() { return _minst.top(); }

private:
	stack<int> _st;    // 普通栈
	stack<int> _minst; // 记录最小元素的栈
};
// 18.栈的压入、弹出序列
// https://www.nowcoder.com/share/jump/3141631241735046087276 
class Solution {
public:
	bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
		//入栈顺序模拟出栈顺序
		int i = 0;
		stack<int> s;
		for (auto& e : pushV)
		{
			s.push(e);
			while (!s.empty() && s.top() == popV[i])//一直连续匹配的话，可能导致出栈为空
			{
				s.pop();
				++i;
			}
		}
		return s.empty();
	}
};
// 19.二叉树的层序遍历
// https://leetcode.cn/problems/binary-tree-level-order-traversal/ 
// 法一：一个队列存结点，一个变量统计当前层数共有的总结点个数，对一层进行操作，共操作次数为当前层数的结点个数
class Solution {
public:
	vector<vector<int>> levelOrder(TreeNode* root) {
		vector<vector<int>> vv;
		if (!root)
			return vv;
		queue<TreeNode*> q1; // 存结点
		size_t i = 1;        // 当前层数的结点个数
		q1.push(root);
		while (!q1.empty()) {
			vector<int> v;
			while (i--) {
				v.push_back(q1.front()->val);
				if (q1.front()->left)
					q1.push(q1.front()->left);
				if (q1.front()->right)
					q1.push(q1.front()->right);
				q1.pop();
			}
			i = q1.size();  //每层结束后更新对应下层的结点个数
			vv.push_back(v);
		}
		return vv;
	}
};
// 法二：借助两个队列，一个存结点，一个存每个结点对应的层
class Solution {
public:
	vector<vector<int>> levelOrder(TreeNode* root) {
		vector<vector<int>> vv;
		if (!root)
			return vv;
		size_t i = 1;
		queue<TreeNode*> q1; // 存结点
		queue<int> q2;       // 存每个结点对应的层
		q1.push(root);
		q2.push(i);
		while (!q1.empty()) {
			vector<int> v;
			while (q2.front() == i) {
				v.push_back(q1.front()->val);
				if (q1.front()->left) {
					q1.push(q1.front()->left);
					q2.push(i + 1);
				}
				if (q1.front()->right) {
					q1.push(q1.front()->right);
					q2.push(i + 1);
				}
				q1.pop();
				q2.pop();
			}
			++i;
			vv.push_back(v);
		}
		return vv;
	}
};
// 20.逆波兰表达式求值
//https://leetcode.cn/problems/evaluate-reverse-polish-notation/ 
class Solution {
public:
	int evalRPN(vector<string>& tokens) {
		stack<int> s1;
		for (int i = 0; i < tokens.size(); i++) {
			string& s2 = tokens[i];
			if (!("+" == s2 || "-" == s2 || "*" == s2 || "/" == s2)) // 数字入栈
				s1.push(stoi(s2));
			else // 符号就进行运算
			{
				int right = s1.top();
				s1.pop();
				int left = s1.top();
				s1.pop();
				switch (s2[0]) {
				case '+':
					s1.push(left + right);
					break;
				case '-':
					s1.push(left - right);
					break;
				case '*':
					s1.push(left * right);
					break;
				case '/':
					s1.push(left / right);
					break;
				}
			}
		}
		return s1.top();
	}
};
// 21.用两个栈实现队列
// https://leetcode.cn/problems/implement-queue-using-stacks/ 
class MyQueue {
public:
	MyQueue() = default;
	void push(int x) { _in.push(x); }
	int pop() {
		if (_out.empty()) {
			while (!_in.empty()) {
				_out.push(_in.top());
				_in.pop();
			}
		}
		int n = _out.top();
		_out.pop();
		return n;
	}
	int peek() {
		if (_out.empty()) {
			while (!_in.empty()) {
				_out.push(_in.top());
				_in.pop();
			}
		}
		return _out.top();
	}
	bool empty() { return _in.empty() && _out.empty(); }
private:
	stack<int> _in;//压栈
	stack<int> _out;//出栈
};
// 22.队列模拟栈
//3 https://leetcode.cn/problems/implement-stack-using-queues/ 
//法一：两个队列模拟栈
class MyStack {
public:
	MyStack() = default;
	void push(int x) {//push麻烦些，保证每次push完后都是栈的出栈顺序
		emp.push(x);//保证空队列每次插入前都是空的，故可用作中转，一来直接往其内插入
		while (!no_emp.empty())//假设非空队列就是出栈顺序，借助空队列实现插入元素变成出栈顺序
		{
			emp.push(no_emp.front());
			no_emp.pop();
		}
		emp.swap(no_emp);//出循环后，空队列是出栈顺序，直接交换
	}
	int pop() {
		int n = no_emp.front();
		no_emp.pop();
		return n;
	}
	int top() {
		return no_emp.front();
	}
	bool empty() {
		return no_emp.empty();
	}
private:
	queue<int> no_emp;//取名非空队列，主要存数据
	queue<int> emp;//取名空队列，只是用作中转，中转后一直保持为空
};
//法二：一个队列模拟栈
class MyStack {
public:
	MyStack() = default;
	void push(int x) {//让push完后保证是出栈顺序
		q.push(x);
		int n = q.size();
		while (--n)
		{
			int front = q.front();
			q.pop();
			q.push(front);
		}
	}
	int pop() {
		int ret = q.front();
		q.pop();
		return ret;
	}
	int top() {
		return q.front();
	}
	bool empty() {
		return q.empty();
	}
private:
	queue<int> q;
};
// 23.数组中第k个最大的元素
// https://leetcode.cn/problems/kth-largest-element-in-an-array/ 
class Solution {
public:
	int findKthLargest(vector<int>& nums, int k) {
		priority_queue<int, vector<int>, greater<>> pq; // 建小堆，大堆无论从空间还是时间来看都不如小堆
		for (int i = 0; i < k; i++)
			pq.push(nums[i]);
		for (int i = k; i < nums.size(); i++) {
			if (pq.top() < nums[i]) {
				pq.pop();
				pq.push(nums[i]);
			}
		}
		return pq.top();
	}
};
// 24.两个数组的交集
// https://leetcode.cn/problems/intersection-of-two-arrays/ 
class Solution {
public:
	vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
		vector<int> v;
		set<int> s1(nums1.begin(), nums1.end());
		set<int> s2(nums2.begin(), nums2.end());
		auto it1 = s1.begin(), it2 = s2.begin();
		while (it1 != s1.end() && it2 != s2.end()) {
			if (*it1 == *it2) {
				v.push_back(*it1);
				++it1;
				++it2;
			}
			else if (*it1 < *it2)
				++it1;
			else
				++it2;
		}
		return v;
	}
};
// 25.环形链表Ⅱ
// https://leetcode.cn/problems/linked-list-cycle-ii/ 
class Solution {//用set解决，set结构保证了天然去重，有重复就说明遇到环了
public:
	ListNode* detectCycle(ListNode* head) {
		if (head == nullptr)
			return head;
		set<ListNode*> s;
		ListNode* cur = head;
		while (cur)
		{
			auto it = s.insert(cur);
			if (it.second == false)
				return *(it.first);
			cur = cur->next;
		}
		return nullptr;
	}
};